首页 > 代码库 > 项目架构开发:数据访问层之Query

项目架构开发:数据访问层之Query

接上文 项目架构开发:数据访问层之Repository

技术分享

 

上一章我们讲了IRepository接口,这张我们来讲IQuery

根据字面意思就可以知道,这次主要讲数据查询,上一章我们只针对单表做了查询的操作,多表联查并没有实现

其实对于任何一个项目来说,多表联查都是比较麻烦的地方,因为项目的“读”操作,特别是多表的“读”,至少占据所有“读”的一半以上

然而至今,据我所知还没有哪一款ORM工具可以灵活处理多表联查;想要不写sql语句,又想性能高,还想用强类型的ling查询方法;这对于多表查询来说比较难

鉴于此,也别做那些别扭的映射了(像NH),而如果用lingtosql我觉得还不如直接写sql来的好;

是开发人员不可能不懂sql,那对多表查询这一块,干脆独立一个Query类出来,专门处理这种事

 

好了这只是我的处理方式,我们来看看

IQuery.cs

 1     public interface IQuery 2     { 3         T QuerySingle<T>(string sql, object paramPairs) where T : class; 4         IEnumerable<T> QueryList<T>(string sql, object paramPairs) where T : class; 5  6         /// <summary>必须带上row_number() over({0}) RowNumber</summary> 7         Tuple<int, IEnumerable<T>> GetPage<T>(Page page, string sql, dynamic paramPairs = null) where T : class; 8          9         Tuple<int, IEnumerable<T>> GetPage<T>(string sql, object paramPairs = null) where T : class;10         int Execute(string sql, dynamic paramPairs = null);11         long Count(string sql, dynamic paramPairs = null);12     }

 

上方法名就可以知道,写sql,然后返回自定义的T或IEnumerable<T>

这里避免了用泛型类,因为某个实体大多数情况下可能也只是需要,上边其中其中的1、2个而已

这里有一个Execute方法,其实不应该放在这的,但是也懒得写另外一个类了,先放着吧

 

Query的实现

技术分享

 

DapperQuery.cs

 1 using Dapper; 2 using Dapper.Contrib.Extensions; 3 using LjrFramework.Common; 4 using LjrFramework.Interface; 5 using System; 6 using System.Collections.Generic; 7 using System.Data; 8 using System.Linq; 9 10 namespace LjrFramework.Data.Dapper11 {12     public class DapperQuery : IQuery13     {14         protected IDbConnection Conn { get; private set; }15 16         public DapperQuery()17         {18             Conn = DbConnectionFactory.CreateDbConnection();19         }20 21         public void SetDbConnection(IDbConnection conn)22         {23             Conn = conn;24         }25 26         public T QuerySingle<T>(string sql, object paramPairs) where T : class27         {28             return Conn.Query<T>(sql, paramPairs).SingleOrDefault();29         }30 31         public IEnumerable<T> QueryList<T>(string sql, object paramPairs) where T : class32         {33             return Conn.Query<T>(sql, paramPairs);34         }35 36         /// <summary>自动分页,必须带上row_number() over({0}) RowNumber</summary>37         public Tuple<int, IEnumerable<T>> GetPage<T>(Page page, string sql, object paramPairs = null) where T : class38         {39             var multi = Conn.GetPage<T>(page.PageIndex, page.PageSize, sql, paramPairs);40             var count = multi.Read<int>().Single();41             var results = multi.Read<T>();42             return new Tuple<int, IEnumerable<T>>(count, results);43         }44         // 需自己实现分页语句45         public Tuple<int, IEnumerable<T>> GetPage<T>(string sql, object paramPairs = null) where T : class46         {47             var multi = Conn.GetGridReader<T>(sql, paramPairs);48             var count = multi.Read<int>().Single();49             var results = multi.Read<T>();50             return new Tuple<int, IEnumerable<T>>(count, results);51         }52 53 54         public int Execute(string sql, object paramPairs = null)55         {56             return Conn.Execute(sql, paramPairs);57         }58 59         public long Count(string sql, object paramPairs = null)60         {61             return Conn.Query<long>(sql, paramPairs).SingleOrDefault();62         }63     }64 }

 

这个实现跟上一章差不多,都是直接调用Conn的扩展方法,

我们进去看看(public Tuple<int, IEnumerable<T>> GetPage<T>(string sql, object paramPairs = null) where T : class)的实现

技术分享

 

可以看到dapper是已经支持sql语句的查询,并且返回多个记录(SqlMapper.GridReader)

 

每次分页都要去手动刷选 页数 与 记录开始行数的话比较麻烦

所有我做了一点小改动,武学用户写分页语句,直接查询就可以了,后台会自动生成分页语句的格式

不过要带上row_number() over({0}) RowNumber;就是上边那个有注释的方法

技术分享

他的实现如下

技术分享

 

这样用户只需要准守一点约束,就会方便很多

这些都是在dapper的Extensions里实现的,用户需要自行修改,自己想要的自定义的功能

好了,Query有效代码写完了,我们看看运行效果

 

Query测试

技术分享

  1 using Autofac;  2 using Company.Project.PO;  3 using LjrFramework.Data.Dapper;  4 using LjrFramework.Common;  5 using LjrFramework.Infrastructure;  6 using LjrFramework.Interface;  7 using Microsoft.VisualStudio.TestTools.UnitTesting;  8 using System;  9 using LjrFramework.Data.UnitOfWork; 10  11 namespace LjrFramework.UnitTest 12 { 13     [TestClass] 14     public class QueryTest 15     { 16         private IQuery query; 17  18         public QueryTest() 19         { 20             var builder = new ContainerBuilder(); 21             builder.RegisterType<DapperQuery>().As<IQuery>(); 22  23             var container = builder.Build(); 24             query = container.Resolve<IQuery>(); 25  26         } 27  28         [TestMethod] 29         public void QuerySingle() 30         { 31             var model = query.QuerySingle<LoginUser>("select * from LoginUser where Id = @Id", new { Id = "854B1FCA-F8D7-4B4B-AA5D-9075F1922721" }); 32  33             Assert.AreEqual(model.LoginName, "lanxiaoke-d318fd40-1b9d-42f8-a002-388b1228012d"); 34         } 35  36         [TestMethod] 37         public void QueryList() 38         { 39             var list = query.QueryList<LoginUser>("select * from LoginUser where LoginName like ‘%‘+ @LoginName + ‘%‘", new { LoginName = "lanxiaoke" }); 40  41             int index = 0; 42             foreach (var user in list) 43             { 44                 index++; 45             } 46  47             Assert.AreEqual(index > 0, true); 48         } 49  50         [TestMethod] 51         public void GetPage() 52         { 53             var page = new Page() 54             { 55                 PageIndex = 1, 56                 PageSize = 10 57             }; 58  59             var results = query.GetPage<LoginUser>(page, 60                 @"select row_number() over(order by CreateTime) RowNumber,* from LoginUser where LoginName like ‘%‘+ @LoginName + ‘%‘", new { LoginName = "lanxiaoke" }); 61  62             var total = results.Item1; 63             var list = results.Item2; 64  65             int index = 0; 66             foreach (var user in list) 67             { 68                 index++; 69             } 70  71             Assert.AreEqual(index > 0, true); 72         } 73  74         [TestMethod] 75         public void GetPage2() 76         { 77             var page = new Page() 78             { 79                 PageIndex = 1, 80                 PageSize = 10 81             }; 82  83             var results = query.GetPage<LoginUser>( 84                 @"select count(*) as TotalCount from LoginUser c where LoginName like ‘%‘+ @LoginName + ‘%‘ 85                   select row_number() over(order by CreateTime) RowNumber,* from LoginUser where LoginName like ‘%‘+ @LoginName + ‘%‘", 86             new { LoginName = "lanxiaoke" }); 87  88             var total = results.Item1; 89             var list = results.Item2; 90  91             int index = 0; 92             foreach (var user in list) 93             { 94                 index++; 95             } 96  97             Assert.AreEqual(index > 0, true); 98         } 99 100         [TestMethod]101         public void Count()102         {103             var row = query.Count("select count(*) from LoginUser");104 105             Assert.AreEqual(row > 1, true);106         }107 108     }109 }

技术分享

自此,多表查询就讲完了

 

项目架构开发系列

  • 项目架构开发:数据访问层之Cache
  • 项目架构开发:数据访问层之Logger
  • 项目架构开发:数据访问层之Repository
  • 项目架构开发:数据访问层之Query
  • 项目架构开发:数据访问层之UnitOfWork

 

项目架构开发:数据访问层之Query