65.9K
CodeProject 正在变化。 阅读更多。
Home

一个开源的 ORM 框架 - Light.Data

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2019年5月23日

CPOL

2分钟阅读

viewsIcon

9960

开源项目 Light.Data 介绍

引言

Light.Data 是一个基于 dotnet standard 2.0 的轻量级 ORM 框架,通过实体模型类的 Attribute 或配置文件关联数据表。 使用核心类 DataContext 对表进行 CRUD 操作。

PM> Install-Package Light.Data

支持的数据库

数据库 引言
SqlServer 需要安装 nuget 安装 Light.Data.Mssql 库,支持 SqlServer 2008 或以上
Mysql 需要安装 nuget 安装 Light.Data.Mysql 库,支持 Mysql5.5 或以上
Postgre 需要安装 nuget 安装 Light.Data.Postgre 库,支持 PostgreSQL9.3 或以上

如何使用

数据库配置

{
  "lightData": {
      "connections": [
          {
             "name": "mssql_db",
             "connectionString": "...",
             "providerName": "Light.Data.Mssql.MssqlProvider, Light.Data.Mssql"
          },
          {
             "name": "mysql_db",
             "connectionString": "...",
             "providerName": "Light.Data.Mysql.MysqlProvider, Light.Data.Mysql"
           }
       ]
    }
}

使用方法

// direct use
DataContext context = new DataContext("mssql");

// create subclass
public class MyDataContext : DataContext
{
    public MyDataContext() : base("mssql")
    {

    }
}

// create subclass with options
public class MyDataContext : DataContext
{
    public MyDataContext(DataContextOptions<MyDataContext> options) : base(options)
    {

    }
}

// direct config connect string and params (IServiceCollection)
service.AddDataContext<MyDataContext>(builder => {
    builder.UseMssql(connectionString);
    builder.SetTimeout(2000);
    builder.SetVersion("11.0");
}, ServiceLifetime.Transient);

// use default configuration file to config (IServiceCollection)
service.AddDataContext<MyDataContext>(DataContextConfiguration.Global, config => {
       config.ConfigName = "mssql";
}, ServiceLifetime.Transient);

对象映射

[DataTable("Te_User", IsEntityTable = true)]
public class TeUser
{
    /// <summary>
    /// Id
    /// </summary>
    /// <value></value>
    [DataField("Id", IsIdentity = true, IsPrimaryKey = true)]
    public int Id
    {
        get;
        set;
    }

    /// <summary>
    /// Account
    /// </summary>
    /// <value></value>
    [DataField("Account")]
    public string Account
    {
        get;
        set;
    }

    /// <summary>
    /// Telephone
    /// </summary>
    /// <value></value>
    [DataField("Telephone", IsNullable = true)]
    public string Telephone
    {
        get;
        set;
    }
    ....
}

子表映射

在派生类 TeUserAndExtend 中,添加一个 public 属性 Extend,其类型为 TeUserExtend,并添加 Attribute RelationFieldAttribute。 在查询 TeUserAndExtend 时,关联的 TeUserExtend 数据也将被检测到,并且也支持一对多

[DataTable("Te_UserExtend", IsEntityTable = true)]
public class TeUserExtend
{
    [DataField("Id", IsIdentity = true, IsPrimaryKey = true)]
    public int Id
    {
        get;
        set;
    }

    [DataField("MainId")]
    public int MainId
    {
        get;
        set;
    }
    
    [DataField("Data", IsNullable = true)]
    public string Data
    {
        get;
        set;
    }
}

public class TeUserAndExtend : TeUser
{
    [RelationField("Id", "MainId")]
    public TeUserExtend Extend
    {
        get;
        set;
    }
}

基本操作

  • 基本 CRUD
  • 批量 CUD
  • 支持事务处理
  • 支持数据字段默认值和自动时间戳
  • 支持数据字段读写控制
  • 查询结果指定类或匿名类输出
  • 将查询结果直接插入到数据表中
var context = new DataContext();
// query single data
var item = context.Query<TeUser>().Where(x => x.Id == 10).First();
// query collection datas
var list = context.Query<TeUser>().Where(x => x.Id > 10).ToList();
// create date
var user = new TeUser() {
  Account = "foo",
  Password = "bar"
};
context.Insert(user);
// update data
user.Password = "bar1";
context.Update(user);
// delete data
context.Delete(user); 

数据聚合

  • 单列数据直接聚合
  • 多列数据分组聚合
  • 格式化分组字段
  • 将聚合数据直接插入到数据表中
// basic
var list = context.Query<TeUser> ()
         .Where (x => x.Id >= 5)
         .GroupBy (x => new LevelIdAgg () {
           LevelId = x.LevelId,
           Data = Function.Count ()
          })
         .ToList ();

// date format
var list = context.Query<TeUser> ()
         .GroupBy (x => new RegDateFormatAgg () {
           RegDateFormat = x.RegTime.ToString("yyyy-MM-dd"),
           Data = Function.Count ()
          })
         .ToList ();

Join-Table 查询

  • 多表连接,支持内连接,左连接和右连接
  • 支持查询结果和聚合数据一起连接
  • 连接查询结果指定类或匿名类输出
  • 将连接查询结果直接插入到数据表中
// inner join
var join = context.Query<TeUser> ()
                  .Join<TeUserExtend>((x,y) => x.Id == y.Id);

// aggregate data join entity table             
var join = context.Query<TeMainTable>()
                  .GroupBy(x => new {
                      MId = x.MId,
                      Count = Function.Count(),
                   })
                  .Join<TeSubTable>((x, y) => x.MId == y.Id);

执行 SQL

  • 直接使用 SQL 和存储过程
  • 支持对象参数
  • 查询结果指定类或匿名类输出
  • 存储过程支持使用输出参数
// basic parameter
var sql = "update Te_User set NickName=@P2 where Id=@P1";
var ps = new DataParameter[2];
ps[0] = new DataParameter("P1", 5);
ps[1] = new DataParameter("P2", "abc");
var executor = context.CreateSqlStringExecutor(sql, ps);
var ret = executor.ExecuteNonQuery();

// object parameter
var sql = "update Te_User set NickName={nickname} where Id={id}";
var executor = context.CreateSqlStringExecutor(sql, new { nickname = "abc", id = 5 });
var ret = executor.ExecuteNonQuery();

单元测试

该项目使用 xUnit 进行单元测试,测试代码地址为:https://github.com/aquilahkj/Light.Data2/tree/master/test

每个数据库都有 300 多组测试,包含 1000 个用例,涵盖了大部分代码。

性能测试

目前,仅在同一台计算机的 Docker SQL Server 2017 for Linux 上使用 EF Core 做简单的 CRUD 性能测试,代码地址 https://github.com/aquilahkj/OrmTest

1000 次 CUD 和单数据查询。

总共 5 轮,每轮 1000 次 CUD 和 1000 次数据查询。

EF 测试结果

Light.Data 测试结果

从对比来看,查询性能几乎相同,插入性能 Light.Data 略好,批量更新也略好。

本文仅作简要介绍,具体使用方法可以参考文档和测试用例。

© . All rights reserved.