zoukankan      html  css  js  c++  java
  • 开源一个基于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

  • 相关阅读:
    vue---lodash的使用
    git---分支的合并
    vue---组件引入及使用的几种方式
    vue---import的几种表现形式
    mock---前端搭建模拟服务
    vue---computed计算属性的使用
    HTML禁止右键复制【两行代码实现】
    SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)
    SQL Server调优系列玩转篇二(如何利用汇聚联合提示(Hint)引导语句运行)
    SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行)
  • 原文地址:https://www.cnblogs.com/aquilahkj/p/10888837.html
Copyright © 2011-2022 走看看