項目架構開發:數據訪問層之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 }

自此,多表查詢就講完了

 

項目架構開發系列

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM