标签:
前言
继之前发的帖子【ORM-Dapper+DapperExtensions】,对Dapper的扩展代码也进行了改进,同时加入Dapper 对Lambda表达式的支持。
由于之前缺乏对Lambda的知识,还是使用了拿来主义。研究了些案例,总归有些问题:
1、只能生成sql、不能将值进行参数化。
2、lambda解析的代码对sql语法的多样式支持不够
3、不开源,反编译后发现可扩展性不强。
最后选择了Dos.ORM(lambda支持的很好,开源的),在这里尊重原创,大家有兴趣去支持下哈。
【作者博客:http://www.cnblogs.com/huxj/ 官方网站:http://ITdos.com/Dos/ORM/Index.html 】
开始研究Dos.ORM , 最后还是要是使用 Dapper 的, 同时还要基于 DapperExtensions的设计思想。
目的是把Dos.ORm的lambda解析核心代码借鉴过来,然后用Dapper去执行。
想法不错,但是实现起来废了一番周折。
大概改动如下:
1、在DapperExtensions原有接口中扩展lambda方法
2、基于DapperExtensions的缓存机制 ,替换了Dos.ORM 对各个字段的和表结构的映射方式。
3、沿用DapperExtensions 中的定义方言接口进行生成sql的扩展
4、扩展了若干方法, 同时去除了Dos.ORM的一些特性.
这里必须要维护DapperExtensions 对实体类的0入侵的原则。
最后发现想让ORM支持Lambda 的语法更多,最后还是要去扩展实体类。(各有利弊得失……)
语法
这里还是直接贴代码了,为了照顾对dapper不熟悉的同学,下面将dapper、DapperExtensions、DapperExtensions+lambda 的语法分块贴出来。
1、实体类
/// <summary> /// HY:实体对象 /// </summary> [Serializable] public class UsersEntity { /// <summary> /// 用户ID /// </summary> public int UserId { get; set; } /// <summary> /// 登录名称 /// </summary> public string LoginName { get; set; } /// <summary> /// 密码 /// </summary> public string Password { get; set; } /// <summary> /// 状态 1:启用 0禁用 /// </summary> public int? Status { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime? CreateTime { get; set; } /// <summary> /// 更新时间 /// </summary> public DateTime? UpdateTime { get; set; } /// <summary> /// 备注 /// </summary> public string Remark { get; set; } } /// <summary> /// Users:实体对象映射关系 /// </summary> [Serializable] public class UsersEntityORMMapper : ClassMapper<UsersEntity> { public UsersEntityORMMapper() { base.Table("Users"); //Map(f => f.UserInfo).Ignore();//设置忽略 //Map(f => f.Name).Key(KeyType.Identity);//设置主键 (如果主键名称不包含字母“ID”,请设置) AutoMap(); } }
2、原生态的Dapper
//做为Demo以下语法的支持, 声明的一个变量 IDbConnection connDemo = this.DBSession.Connection; IEnumerable<UsersEntity> listDemo = connDemo.Query<UsersEntity>("SELECT * FROM Users AS u "); IEnumerable<UsersEntity> listDemo1 = connDemo.Query<UsersEntity>("SELECT * FROM Users AS u WHERE u.UserId=@UserId AND u.LoginName LIKE @LoginName", new { UserId = 11, LoginName = "%王老五%" }); IEnumerable<UsersEntity> listDemo2 = connDemo.Query<UsersEntity>("SELECT * FROM Users AS u WHERE u.UserId IN @UserIds ", new { UserIds = new int[] { 1, 2, 3 }.AsEnumerable() }); string sqlDemo = @"SELECT * FROM Users AS u LEFT JOIN UserInfo AS ui ON u.UserId = ui.UserId"; IEnumerable<UsersModel> listDemo3 = connDemo.Query<UsersModel, UserInfoEntity, UsersModel>(sqlDemo, (user, userinfo) => { user.UserInfo = userinfo; return user; }).ToList(); string sqlDemo1 = @"SELECT * FROM Users AS u WHERE u.UserId=@UserId SELECT * FROM UserInfo AS ui WHERE ui.UserId=@UserId"; using (var multi = connDemo.QueryMultiple(sqlDemo1, new { UserId = 1 })) { var user = multi.Read<UsersEntity>().Single(); var userinfo = multi.Read<UserInfoEntity>().Single(); } connDemo.Execute("sql 语句"); //存储过程 var UsersEntity = connDemo.Query<UsersEntity>("spGetUser", new { Id = 1 }, commandType: CommandType.StoredProcedure).SingleOrDefault();
2、DapperExtensions
//实体类 UsersEntity entity = new UsersEntity(); int userId = this.Insert(entity);//插入 bool isSuccess = this.Update(entity);//更新 int count = this.Delete(entity);//删除 entity = this.GetById(1);//获得实体 int count1 = this.Count(new { ID = 1 }); //数量 //查询所有 IEnumerable<UsersEntity> list = this.GetAll(); //条件查询 IList<ISort> sort = new List<ISort>(); sort.Add(new Sort { PropertyName = "UserId", Ascending = false }); IEnumerable<UsersEntity> list1 = this.GetList(new { UserId = 1, Name = "123" }, sort); //orm 拼接条件 查询 繁琐 不灵活 不太好用 IList<IPredicate> predList = new List<IPredicate>(); predList.Add(Predicates.Field<UsersEntity>(p => p.LoginName, Operator.Like, "不知道%")); predList.Add(Predicates.Field<UsersEntity>(p => p.UserId, Operator.Eq, 1)); IPredicateGroup predGroup = Predicates.Group(GroupOperator.And, predList.ToArray()); list = this.GetList(predGroup); //分页查询 long allRowsCount = 0; this.GetPageList(1, 10, out allRowsCount, new { ID = 1 }, sort);
3、DapperExtensions+lambda
//SELECT [Users].[UserId], // [Users].[LoginName], // [Users].[Password] //FROM [Users] //WHERE [Users].[LoginName] = @LoginName_1 var fromDemo = this.LambdaQuery().Select(p => new { p.UserId, p.LoginName, p.Password }) //不支持As .Where(p => p.LoginName == "很好很强大"); //支持 返回 DataReader、DataSet、DataTable、 泛型集合 fromDemo.ToDataReader(); fromDemo.ToDataSet(); fromDemo.ToDataTable(); IEnumerable<UsersModel> list = fromDemo.ToList<UsersModel>(); var select = new Select<UsersEntity>(); select.AddSelect(p => p.Remark.As("Remark")); //Expression<Func<T, bool>>类型支持 as 语法 fromDemo = this.LambdaQuery().AddSelect(select); // SELECT [Users].[UserId], // [Users].[LoginName], // [Users].[Password], // [Users].[Status], // [Users].[CreateTime], // [Users].[UpdateTime], // [Users].[Remark] //FROM [Users] //WHERE ( // ( // ([Users].[LoginName] LIKE @LoginName_1) // AND ([Users].[Status] NOT IN (@Status_2, @Status_3, @Status_4)) // ) // AND ([Users].[CreateTime] >= @CreateTime_5) // ) // AND ([Users].[UpdateTime] IS NOT NULL) var fromDemo2 = this.LambdaQuery().Where(p => p.LoginName.Like("%王老五%") //like && p.Status.NotIn<string>("1", "2", "3") //in or not in && p.CreateTime >= Convert.ToDateTime("2016-01-21") //时间比较 && p.UpdateTime.IsNotNull() //is null ); //SELECT [Users].[UserId], // [Users].[LoginName], // [Users].[Password], // [Users].[Status], // [Users].[CreateTime], // [Users].[UpdateTime], // [Users].[Remark] //FROM [Users] //WHERE ( // ( // ([Users].[LoginName] LIKE @LoginName_1) // AND ([Users].[Status] = @Status_2) // ) // OR ([Users].[UserId] = @UserId_3) // ) var where = new Where<UsersEntity>(); where.And(p => p.LoginName.Like("%李二蛋%") && p.Status == 1); where.Or(p => p.UserId == 1); var fromDemo3 = this.LambdaQuery().Where(where); //SELECT [Users].[UserId], // [Users].[LoginName], // [Users].[Password], // [Users].[Status], // [Users].[CreateTime], // [Users].[UpdateTime], // [Users].[Remark] //FROM [Users] //ORDER BY // CreateTime ASC, // UpdateTime ASC, // UserId DESC var fromDemo4 = this.LambdaQuery().OrderBy(p => new { p.CreateTime, p.UpdateTime }).AddOrderByDescending(p => new { p.UserId }); //"SELECT * FROM [Users] INNER JOIN UserInfo ON ([Users].[UserId] = [UserInfo].[UserId]) " var fromDemo5 = this.LambdaQuery().InnerJoin<UserInfoEntity>((u, ui) => u.UserId == ui.UserId); //SELECT DISTINCT TOP 100 * //FROM [Users] WITH (NOLOCK) INNER // JOIN UserInfo WITH (NOLOCK) // ON ([Users].[UserId] = [UserInfo].[UserId]) var fromDemo6 = this.LambdaQuery() .InnerJoin<UserInfoEntity>((u, ui) => u.UserId == ui.UserId).WithNoLock().Top(100).Distinct(); //SELECT TOP(10) [_proj].* //FROM ( // SELECT ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) AS [_row_number], // * // FROM [Users] WITH (NOLOCK) LEFT // JOIN UserInfo WITH (NOLOCK) // ON ([Users].[UserId] = [UserInfo].[UserId]) // WHERE ([Users].[UserId] > @UserId_1) // AND ([UserInfo].[Sex] = @Sex_2) // ) [_proj] //WHERE [_proj].[_row_number] >= @_pageStartRow //ORDER BY // [_proj].[_row_number] var fromDemo7 = this.LambdaQuery() .LeftJoin<UserInfoEntity>((u, ui) => u.UserId == ui.UserId).WithNoLock() .Where<UserInfoEntity>((u, ui) => u.UserId > 1 && ui.Sex == 1) .Page(2, 10); //DELETE //FROM [Users] //WHERE ([Users].[Status] = @Status_1) // AND ( //[Users].[CreateTime] > @CreateTime_2 var deleteDemo = this.LambdaDelete() .Where(p => p.Status == 1 && p.CreateTime > DateTime.Now); //UPDATE [Users] //SET [Users].[Remark] = @Remark_3 //WHERE [Users].[Status] = @Status_4 var updateDemo = this.LambdaUpdate() .Set(p => p.Remark == "Remark") .Where(p => p.Status == 1);
对于lambda 支持 select + As 、where 、各种左右连接、 orderby 、grouy by、 HAVING、 WITH(NOLOCK) (支持sqlserver)、 Top、Distinct、
(支持sql垮数据库查询,加入DbName、SchemaName配置)
简单的语法都支持了,但是还有些特殊的sql 语法 介于Lambda的语法问题暂时没办法支持。不过Dos.ORM做到了一些特殊的支持。
之前也和Dos.ORM的作者交流过。 目前都不支持 select * from User a INNER join User b on a.id=b.pid 这类 别名且自join查询,实现起来很麻烦。
这里我就放弃了,有些功能在考虑到性能和设计方面得不偿失。
比如一个特别复杂的sql ,非要用ORM来实现,那其实已经超出ORM的能力范围了。且不论性能问题和代码支持问题, 单单代码可读性就降低很多啊
相信直接看sql 比直接看 orm语法 看的爽吧 。
性能:
用lambda生成sql用时也就2,3 毫秒的样子, 所以在执行和映射能力方面我就不担心了。最后还是写了个小测试:
之前有很多小伙伴不太了解如果和使用或者调用, 这里简单的写个Demo, (下载地址在下面 )
1.针对Repository的类图如下:
2、Demo的 架构如下:
欢迎老大们拍砖指点。
相关文章:
搭建一套自己实用的.net架构(3)【ORM-Dapper+DapperExtensions】
原文链接:http://www.cnblogs.com/hy59005271/p/5501165.html
搭建一套自己实用的.net架构(3)续 【ORM Dapper+DapperExtensions+Lambda】
标签:
原文地址:http://www.cnblogs.com/hy59005271/p/5501165.html