你的位置:首页 > ASP.net教程

[ASP.net教程]搭建一套自己实用的.net架构续 【ORM Dapper+DapperExtensions+Lambda】


      前言

      继之前发的帖子【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的类图如下:

 

欢迎老大们拍砖指点。

 

 

DapperExtensions.Demo

 

相关文章:

搭建一套自己实用的.net架构(3)【ORM-Dapper+DapperExtensions】

 

 

原文链接:http://www.cnblogs.com/hy59005271/p/5501165.html