开源一个基于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写的网络程 ...
随机推荐
- ubuntu 14.04安装nodejs
http://stackoverflow.com/questions/32902699/cannot-install-ember-on-ubuntu-1404/33495134
- [Tools] Convert SVG to a PDF in Node with PDFKit and SVG.js
Given a epxress application and an svg template, we want to draw some text, date onto it and convert ...
- 【基础练习】【线性DP】codevs3027 线段覆盖2题解
文章被盗还是非常严重,加版权信息 转载请注明出处 [ametake版权全部]http://blog.csdn.net/ametake欢迎来看看 这道题目是线性动归 可是思想和背包有些类似 事实上线性动 ...
- 这样看ACM是不是更好?
如果搞ACM只是为了拿奖,为了保研,这样太功利,整个过程都会变得没意思.我说过我同时看中过程和结果. 其实ACM解题也不是那么没意思,每次AC都有一种非常棒的成就感,每个题目就像是一个解谜游戏,完成了 ...
- Js两种post方式(转)
第一种提交post的方式是传统方式,判断浏览器进行post请求. <SCRIPT stype=text/javascript> var xmlobj; //定义XMLHttpRequest ...
- mysql有哪几种索引
从数据结构角度 1. B+树索引(O(log(n))) 2. hash索引 3. FULLTEXT索引 4. R-Tree索引 从物理存储角度 1. 聚集索引 2. 非聚集索引 从逻辑角度 ...
- VB.NE总结
VB.NET视频看完了.但台湾微软资深讲师的声音还回荡在我的脑海中啊.刚開始听两位老师的讲课那是一个纠 结.感觉不亚于听英语听力训练.后来看到王鹏同学转载的台湾计算机术语和大陆计算机术语的对比,我才明 ...
- vs2010 msvcr100.DLL 丢失!!! 用release 就可以了
- AppFuse 3的乱码问题
书接上回:AppFuse 3常见问题与解决方法,一个新问题:乱码! 在3.0.0版本号下,运行mvn appfuse:full-source命令后使用mvn jetty:run启动工程,页面上就出现了 ...
- es 300G 数据删除 执行计划 curl REST 操作
es 300G 数据删除 [es union_2017执行计划] [测试执行环境]线上D服务器[测试用例]get:curl -XGET ES:9200/_cat/indices?v post:curl ...