开源一个基于dotnet standard的轻量级的ORM框架-Light.Data

   还在dotnet framework 2.0的时代,当时还没有EF,而NHibernate之类的又太复杂,并且自己也有一些特殊需求,如查询结果直接入表、水平分表和新增数据默认值等,就试着折腾个轻量点ORM框架,就慢慢有了这个Light.Data,也一直在公司和个人的项目使用,后来陆陆续续也支持了跨数据库并在mono中使用。到了dotnet core来临,也尝试移植,1.0的时候由于类库不完善,效果不理想。2.0的基本完善了,由于个人严重的强迫症和拖延症,一直在折腾细节、写单元测试和磨文档,磨到差不多3.0快来了。。。。

    不说废话了,Light.Data是一个轻量级的基于dotnet standard 2.0的ORM框架, 通过对实体模型类的Attribute或者配置文件进行配置与数据表的对应关系. 使用核心类DataContext对数据表进行CURD的操作.

PM> Install-Package Light.Data

支持数据库
数据库说明
SqlServer 安装Light.Data.Mssql类库, 支持SqlServer 2008或以上
Mysql 安装Light.Data.Mysql类库, 支持Mysql 5.5或以上
Postgre 安装Light.Data.Postgre类库, 支持Postgre9.3或以上

 

 

连接配置

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

 

使用方式

// 直接使用
DataContext context = new DataContext("mssql");

// 创建子类
public class MyDataContext : DataContext
{
    public MyDataContext() : base("mssql")
    {

    }
}

// 创建配置子类
public class MyDataContext : DataContext
{
    public MyDataContext(DataContextOptions<MyDataContext> options) : base(options)
    {

    }
}

// 直接配置连接字符串和参数 (IServiceCollection)
service.AddDataContext<MyDataContext>(builder => {
    builder.UseMssql(connectionString);
    builder.SetTimeout(2000);
    builder.SetVersion("11.0");
}, ServiceLifetime.Transient);

// 默认配置文件配置 (IServiceCollection)
service.AddDataContext<MyDataContext>(DataContextConfiguration.Global, config => {
       config.ConfigName = "mssql";
}, ServiceLifetime.Transient);

 

对象映射

 1 [DataTable("Te_User", IsEntityTable = true)]
 2 public class TeUser
 3 {
 4     /// <summary>
 5     /// Id
 6     /// </summary>
 7     /// <value></value>
 8     [DataField("Id", IsIdentity = true, IsPrimaryKey = true)]
 9     public int Id
10     {
11         get;
12         set;
13     }
14 
15     /// <summary>
16     /// Account
17     /// </summary>
18     /// <value></value>
19     [DataField("Account")]
20     public string Account
21     {
22         get;
23         set;
24     }
25 
26     /// <summary>
27     /// Telephone
28     /// </summary>
29     /// <value></value>
30     [DataField("Telephone", IsNullable = true)]
31     public string Telephone
32     {
33         get;
34         set;
35     }
36     ....
37 }

 

子表对象关联

在继承类`TeUserAndExtend`中添加一个类型是`TeUserExtend`的公共属性`Extend`, 并加上Attribute`RelationField`, 在查询`TeUserAndExtend`时, 会把关联的`TeUserExtend`数据也一并查出. 并支持一对多的关系
 1 [DataTable("Te_UserExtend", IsEntityTable = true)]
 2 public class TeUserExtend
 3 {
 4     [DataField("Id", IsIdentity = true, IsPrimaryKey = true)]
 5     public int Id
 6     {
 7         get;
 8         set;
 9     }
10 
11     [DataField("MainId")]
12     public int MainId
13     {
14         get;
15         set;
16     }
17     
18     [DataField("Data", IsNullable = true)]
19     public string Data
20     {
21         get;
22         set;
23     }
24 }
25 
26 
27 public class TeUserAndExtend : TeUser
28 {
29     [RelationField("Id", "MainId")]
30     public TeUserExtend Extend
31     {
32         get;
33         set;
34     }
35 }

 

基本操作

  • 基本CURD
  • 批量CUD
  • 支持事务处理
  • 支持数据字段默认值和自动时间戳
  • 支持数据字段读写控制
  • 查询结果指定类或匿名类输出
  • 查询直接插入数据表
 1 var context = new DataContext();
 2 // 查询单个数据
 3 var item = context.Query<TeUser>().Where(x => x.Id == 10).First();
 4 // 查询集合数据
 5 var list = context.Query<TeUser>().Where(x => x.Id > 10).ToList();
 6 // 新增数据
 7 var user = new TeUser() {
 8     Account = "foo",
 9     Password = "bar"
10 };
11 context.Insert(user);
12 // 修改数据
13 user.Password = "bar1";
14 context.Update(user);
15 // 删除数据
16 context.Delete(user);

 

数据汇总

  • 单列数据直接汇总
  • 多列数据分组汇总
  • 格式化分组字段
  • 汇总数据直接插入数据表
 1 // 普通汇总
 2 var list = context.Query<TeUser> ()
 3                   .Where (x => x.Id >= 5)
 4                   .Aggregate (x => new LevelIdAgg () {
 5                       LevelId = x.LevelId,
 6                       Data = Function.Count ()
 7                    })
 8                   .ToList ();
 9 
10 // 日期格式化统计
11 var list = context.Query<TeUser> ()
12                   .Aggtrgate (x => new RegDateFormatAgg () {
13                       RegDateFormat = x.RegTime.ToString("yyyy-MM-dd"),
14                       Data = Function.Count ()
15                    })
16                   .ToList ();    

 

连表查询

  • 多表连接, 支持内连接, 左连接和右连接
  • 支持查询结果和汇总数据连接
  • 连接查询结果指定类或匿名类输出
  • 连接查询结果直接插入数据表
 1 // 内连接
 2 var join = context.Query<TeUser> ()
 3                   .Join<TeUserExtend>((x,y) => x.Id == y.Id);
 4 
 5 // 统计结果连接实体表             
 6 var join = context.Query<TeMainTable>()
 7                   .GroupBy(x => new {
 8                       MId = x.MId,
 9                       Count = Function.Count(),
10                    })
11                   .Join<TeSubTable>((x, y) => x.MId == y.Id);

 

执行SQL语句

  • 直接使用SQL语句和存储过程
  • 支持对象参数
  • 查询结果指定类或匿名类输出
  • 存储过程支持output参数
 1 // 普通参数
 2 var sql = "update Te_User set NickName=@P2 where Id=@P1";
 3 var ps = new DataParameter[2];
 4 ps[0] = new DataParameter("P1", 5);
 5 ps[1] = new DataParameter("P2", "abc");
 6 var executor = context.CreateSqlStringExecutor(sql, ps);
 7 var ret = executor.ExecuteNonQuery();
 8 
 9 // 对象参数
10 var sql = "update Te_User set NickName={nickname} where Id={id}";
11 var executor = context.CreateSqlStringExecutor(sql, new { nickname = "abc", id = 5 });
12 var ret = executor.ExecuteNonQuery();

单元测试

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

每种数据库均有300多组1000多用例的测试,覆盖大部分代码。

 

性能测试

目前只跟EF Core在同一电脑的Docker上的Sql Server 2017 for linux中做简单的增删改查性能对比测试,代码地址 https://github.com/aquilahkj/OrmTest

1000次的增删改和单条数据查询

共5轮,每轮1000条的增删改和1000条数据查询

EF的测试结果

Light.Data测试结果

从对比看,查询性能两者差不多,新增性能Light.Data稍微占优,批量更新也稍微占优。

另外值得一提的是Postgre,批量增删改性能比Sql Server快2,3倍,看来以后也要好好研究一下。

 以上均是非严谨测试,仅供参考。

 

最后

本文只是简单的介绍,具体使用方法可以查看文档和参考测试用例,如有需要会写具体使用的文章。

Light.Data这个项目这么多年来个人一直维护,也在不断优化,不断成长,但一直养在深闺,好不容易折腾开源也是希望能共享出去,给有需要的朋友多个选择,同时也是给自己这么多年码农的见证。

虽然现在ORM的框架非常非常多,也不是什么热门新鲜事物,但总归是个基础的东西。

如果有朋友喜欢,不妨试试,可以的话,给个Star,十分欢迎意见或建议 :D

posted on 2019-05-22 17:36  aquilahkj  阅读(985)  评论(7编辑  收藏  举报