开源一个基于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或以上 |
使用文档: https://aquilahkj.github.io/Light.Data.Site/#/zh-cn/
Github: https://github.com/aquilahkj/Light.Data2
连接配置
{
"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();
builder.SetVersion("11.0");
}, ServiceLifetime.Transient); // 默认配置文件配置 (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;
}
....
}
子表对象关联
[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;
}
}
基本操作
- 基本CURD
- 批量CUD
- 支持事务处理
- 支持数据字段默认值和自动时间戳
- 支持数据字段读写控制
- 查询结果指定类或匿名类输出
- 查询直接插入数据表
var context = new DataContext();
// 查询单个数据
var item = context.Query<TeUser>().Where(x => x.Id == ).First();
// 查询集合数据
var list = context.Query<TeUser>().Where(x => x.Id > ).ToList();
// 新增数据
var user = new TeUser() {
Account = "foo",
Password = "bar"
};
context.Insert(user);
// 修改数据
user.Password = "bar1";
context.Update(user);
// 删除数据
context.Delete(user);
数据汇总
- 单列数据直接汇总
- 多列数据分组汇总
- 格式化分组字段
- 汇总数据直接插入数据表
// 普通汇总
var list = context.Query<TeUser> ()
.Where (x => x.Id >= )
.Aggregate (x => new LevelIdAgg () {
LevelId = x.LevelId,
Data = Function.Count ()
})
.ToList (); // 日期格式化统计
var list = context.Query<TeUser> ()
.Aggtrgate (x => new RegDateFormatAgg () {
RegDateFormat = x.RegTime.ToString("yyyy-MM-dd"),
Data = Function.Count ()
})
.ToList ();
连表查询
- 多表连接, 支持内连接, 左连接和右连接
- 支持查询结果和汇总数据连接
- 连接查询结果指定类或匿名类输出
- 连接查询结果直接插入数据表
// 内连接
var join = context.Query<TeUser> ()
.Join<TeUserExtend>((x,y) => x.Id == y.Id); // 统计结果连接实体表
var join = context.Query<TeMainTable>()
.GroupBy(x => new {
MId = x.MId,
Count = Function.Count(),
})
.Join<TeSubTable>((x, y) => x.MId == y.Id);
执行SQL语句
- 直接使用SQL语句和存储过程
- 支持对象参数
- 查询结果指定类或匿名类输出
- 存储过程支持output参数
// 普通参数
var sql = "update Te_User set NickName=@P2 where Id=@P1";
var ps = new DataParameter[];
ps[] = new DataParameter("P1", );
ps[] = new DataParameter("P2", "abc");
var executor = context.CreateSqlStringExecutor(sql, ps);
var ret = executor.ExecuteNonQuery(); // 对象参数
var sql = "update Te_User set NickName={nickname} where Id={id}";
var executor = context.CreateSqlStringExecutor(sql, new { nickname = "abc", id = });
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
开源一个基于dotnet standard的轻量级的ORM框架-Light.Data的更多相关文章
- 推荐一个适用于SpringBoot项目的轻量级HTTP客户端框架,快来试试它!
在SpringBoot项目直接使用okhttp.httpClient或者RestTemplate发起HTTP请求,既繁琐又不方便统一管理.因此,在这里推荐一个适用于SpringBoot项目的轻量级HT ...
- 基于java注解实现自己的orm框架
ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关系. 现在常见的 ...
- eShopOnContainers 是一个基于微服务的.NET Core示例框架
找到一个好的示例框架很难,但不是不可能.大多数是小型Todo风格的应用程序,通常基于SimpleCRUD.值得庆幸的是,Microsoft已经为eShopOnContainers创建了一个基于微服务的 ...
- 亲手搭建一个基于Asp.Net WebApi的项目基础框架1
目标:教大家搭建一个简易的前后端分离的项目框架. 目录: 1:关于项目架构的概念 2:前后端分离的开发模式 3:搭建框架的各个部分 这段时间比较闲,所以想把之前项目里用到的一些技术写到博客里来,分享给 ...
- 亲手搭建一个基于Asp.Net WebApi的项目基础框架4
实现目的:配置website端与服务端对接 1:配置好各项配置文件 2:server端编写接口客户端调用 1.1首先配置文件有log4的配置文件,有config的配置文件,还有服务列表的配置文件 首先 ...
- 开源一个基于天天团购的团购app
可能大家都知道天天团购开源系统,一个做团购的开源项目很赞,前些日子做了基于天天团购系统做的团购客户端和移动端服务器!源代码放出,有了解的可以看看,希望收益! 先说服务器:app的服务器,基于天天团购的 ...
- C# 开源一个基于 yarp 的 API 网关 Demo,支持绑定 Kubernetes Service
关于 Neting 刚开始的时候是打算使用微软官方的 Yarp 库,实现一个 API 网关,后面发现坑比较多,弄起来比较麻烦,就放弃了.目前写完了查看 Kubernetes Service 信息.创建 ...
- [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏
前言 这款安卓小游戏是基于SurfaceView的飞行射击类游戏,采用Java来写,没有采用游戏引擎,注释详细,条理比较清晰,适合初学者了解游戏状态转化自动机和一些继承与封装的技巧. 效果展示 ...
- 开源一个基于nio的java网络程序
因为最近要从公司离职,害怕用nio写的网络程序没有人能看懂(或许是因为写的不好吧),就调整成了mina(这样大家接触起来非常方便,即使没有socket基础,用起来也不难),所以之前基于nio写的网络程 ...
随机推荐
- es删除文档或者删除索引
es删除文档或者删除索引 学习了:https://www.imooc.com/video/15771 删除文档: DELETE http://127.0.0.1:9200/people/man/1 删 ...
- 【从零学习openCV】IOS7下的openCV开发起步(Xcode5.1.1&openCV2.49)
前言: 开发IOS7已经有一月的时间了.近期在准备推研的事,有点想往CV方向发展.于是開始自学openCV. 关注CSDN已经非常久了.也从非常多博主那学到了非常多知识,于是我也从这周开启自己的blo ...
- ALERT日志中常见监听相关报错之三:ORA-609 TNS-12537 and TNS-12547 or TNS-12170 TNS-12535错误的排查
1.11G中ALERT日志中有报错ORA-609 TNS-12537 and TNS-12547 or TNS-12170 12170, 'TNS-12535等问题的解决方法: Troublesho ...
- [java][db]JAVA分布式事务原理及应用
JTA(Java Transaction API)同意应用程序运行分布式事务处理--在两个或多个网络计算机资源上訪问而且更新数据.JDBC驱动程序的JTA支持极大地增强了数据訪问能力. 本文的目的是 ...
- 【转载】一张“神图”看懂单机/集群/热备/磁盘阵列(RAID)
单机部署(stand-alone):只有一个饮水机提供服务,服务只部署一份 集群部署(cluster):有多个饮水机同时提供服务,服务冗余部署,每个冗余的服务都对外提供服务,一个服务挂掉时依然可用 热 ...
- MAC Intellij IDEA 经常使用快捷键(本人亲自測试过)
MAC Intellij IDEA 经常使用快捷键 keymap 设置 MAC OS X 10.5+ alt+f7查找变量方法使用的地方 F3加入书签 Ctrl + O快捷覆写方法 Alt + F3 ...
- (转)OutOfMemory时抓取heap 快照
转自:https://testerhome.com/topics/579 首先说一下,在程序没有崩溃的时候如何抓取heap快照.这个大家应该都知道,在ddms中自带此功能. 见上图首先我们选中一个 ...
- 如何在外部采用AES-128对HLS的TS流进行加密
http://www.wowza.cn/hls/howToSecureHlsByAes128External
- 设计模式学习笔记——Prototype原型模式
原型模型就是克隆. 还有深克隆.浅克隆,一切听上去都那么耳熟能详.
- MapReduce算法形式五:TOP—N
案例五:TOP—N 这个问题比较常见,一般都用于求前几个或者后几个的问题,shuffle有一个默认的排序是正序的,但如果需要逆序的并且暂时还不知道如何重写shuffle的排序规则的时候就用以下方法就行 ...