项目架构开发:数据访问层之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.Dapper
11 {
12     public class DapperQuery : IQuery
13     {
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 : class
27         {
28             return Conn.Query<T>(sql, paramPairs).SingleOrDefault();
29         }
30 
31         public IEnumerable<T> QueryList<T>(string sql, object paramPairs) where T : class
32         {
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 : class
38         {
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 : class
46         {
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 }

自此,多表查询就讲完了

 

项目架构开发系列

 

posted @ 2017-03-05 21:56 蓝建荣 阅读(...) 评论(...) 编辑 收藏