數據訪問層之Repository


數據訪問層之Repository

 

接上文 項目架構開發:數據訪問層之Logger

 

本章我們繼續IRepository開發,這個倉儲與領域模式里邊的倉儲有區別,更像一個工具類,也就是有些園友說的“偽倉儲”,

這個倉儲只實現單表的CURD與Query,都是通過主鍵ID或拉姆達表達式進行操作的,返回的都是單表的實體或實體集合,

多表的在IQuery接口中再講;雖然如此,但是如果與“活動記錄”開發模式搭配的話,會非常合適,可以減少開發的時間

及出錯幾率,更符合開發人員的類型調用習慣

 

IRepository.cs

復制代碼
 1     public interface IRepository<T> where T : class
 2     {
 3         void Add(T entity);
 4         void AddBatch(IEnumerable<T> entitys);
 5         void Update(T entity);
 6         void Delete(T entity);
 7         void Delete(string Id);
 8         void Delete(int Id);
 9         void Delete(Guid Id);
10         T Get(string Id);
11         T Get(Guid Id);
12         T Get(int Id);
13         T Get(T entity);
14         T Get(Expression<Func<T, bool>> func);
15         IEnumerable<T> GetAll();
16         IEnumerable<T> GetList(Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null);
17         Tuple<int, IEnumerable<T>> GetPage(Page page, Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null);
18         long Count(Expression<Func<T, bool>> where = null);
19     }
復制代碼

 

倉儲的實現

 

這里我們只實現dapper的適配,EF有時間再搞吧

dapper大家應該都比較熟悉吧,不懂的朋友可以在園中搜索一下啊,很多案例

 

DapperRepository.cs

復制代碼
  1 using Dapper.Contrib.Extensions;
  2 using LjrFramework.Common;
  3 using LjrFramework.Interface;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Data;
  7 using System.Linq;
  8 using System.Linq.Expressions;
  9 
 10 namespace LjrFramework.Data.Dapper
 11 {
 12     public class DapperRepository<T> : IRepository<T> where T : class
 13     {
 14         protected IDbConnection Conn { get; private set; }
 15 
 16         public DapperRepository()
 17         {
 18             Conn = DbConnectionFactory.CreateDbConnection();
 19         }
 20 
 21         public void SetDbConnection(IDbConnection conn)
 22         {
 23             Conn = conn;
 24         }
 25 
 26         public void Add(T entity)
 27         {
 28             Conn.Insert<T>(entity);
 29         }
 30 
 31         public void AddBatch(IEnumerable<T> entitys)
 32         {
 33             foreach (T entity in entitys)
 34             {
 35                 Add(entity);
 36             }
 37         }
 38 
 39         public void Update(T entity)
 40         {
 41             Conn.Update(entity);
 42         }
 43 
 44         public void Delete(T entity)
 45         {
 46             Conn.Delete(entity);
 47         }
 48 
 49         public void Delete(string Id)
 50         {
 51             var entity = Get(Id);
 52             if (entity == null) return;
 53 
 54             Delete(entity);
 55         }
 56 
 57         public void Delete(int Id)
 58         {
 59             var entity = Get(Id);
 60             if (entity == null) return;
 61 
 62             Delete(entity);
 63         }
 64         public void Delete(Guid Id)
 65         {
 66             var entity = Get(Id);
 67             if (entity == null) return;
 68 
 69             Delete(entity);
 70         }
 71 
 72         public T Get(T entity)
 73         {
 74             return Conn.Get<T>(entity);
 75         }
 76 
 77         public T Get(Guid Id)
 78         {
 79             return Conn.Get<T>(Id);
 80         }
 81 
 82         public T Get(string Id)
 83         {
 84             return Conn.Get<T>(Id);
 85         }
 86 
 87         public T Get(int Id)
 88         {
 89             return Conn.Get<T>(Id);
 90         }
 91 
 92         public T Get(Expression<Func<T, bool>> func)
 93         {
 94             var linqToWhere = new LinqToWhere<T>();
 95             linqToWhere.Parse(func);
 96             
 97             return Conn.GetByFunc<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
 98         }
 99 
100         public IEnumerable<T> GetAll()
101         {
102             return Conn.GetAll<T>();
103         }
104 
105         public IEnumerable<T> GetList(Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null)
106         {
107             where = where.And(order);
108 
109             var linqToWhere = new LinqToWhere<T>();
110             linqToWhere.Parse(where);
111 
112             return Conn.GetListByFunc<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
113         }
114 
115         public Tuple<int, IEnumerable<T>> GetPage(Page page, Expression<Func<T, bool>> where = null, Expression<Func<T, bool>> order = null)
116         {
117             where = where.And(order);
118 
119             var linqToWhere = new LinqToWhere<T>();
120             linqToWhere.Parse(where);
121 
122             var multi = Conn.GetPage<T>(page.PageIndex, page.PageSize, linqToWhere.Order, linqToWhere.Where, linqToWhere.KeyValuePairs);
123             var count = multi.Read<int>().Single();
124             var results = multi.Read<T>();
125 
126             return new Tuple<int, IEnumerable<T>>(count, results);
127         }
128 
129         public long Count(Expression<Func<T, bool>> where = null)
130         {
131             var linqToWhere = new LinqToWhere<T>();
132             linqToWhere.Parse(where);
133 
134             return Conn.Count<T>(linqToWhere.Where, linqToWhere.KeyValuePairs);
135         }
136     }
137 }
復制代碼

 

注意標紅的那行,Conn的所有方法都是在命名空間(Dapper.Contrib.Extensions)下的擴展方法

我們看看其中的Insert實現方式,為什么直接傳遞T就可以,而不用寫sql語句

可以看到,dapper后台是遍歷實體的屬性,最后也是拼湊成符合格式的sql語句;

這一點也可以自己擴展,有很大的便利性,所以他寫在Extensions中

 

DbConnectionFactory.cs 也很簡單,是dapper支持多數據庫的工廠類

復制代碼
 1 public class DbConnectionFactory
 2     {
 3         private static readonly string connectionString;
 4         private static readonly string databaseType;
 5 
 6         static DbConnectionFactory()
 7         {
 8             var collection = ConfigurationManager.ConnectionStrings["connectionString"];
 9             connectionString = collection.ConnectionString;
10             databaseType = collection.ProviderName.ToLower();
11         }
12 
13         public static IDbConnection CreateDbConnection()
14         {
15             IDbConnection connection = null;
16             switch (databaseType)
17             {
18                 case "system.data.sqlclient":
19                     connection = new System.Data.SqlClient.SqlConnection(connectionString);
20                     break;
21                 case "mysql":
22                     //connection = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
23                     break;
24                 case "oracle":
25                     //connection = new Oracle.DataAccess.Client.OracleConnection(connectionString);
26                     //connection = new System.Data.OracleClient.OracleConnection(connectionString);
27                     break;
28                 case "db2":
29                     connection = new System.Data.OleDb.OleDbConnection(connectionString);
30                     break;
31                 default:
32                     connection = new System.Data.SqlClient.SqlConnection(connectionString);
33                     break;
34             }
35             return connection;
36         }
37     }
復制代碼

 

自此,dapper適配的倉儲就完成了

我們在測試項目中看看效果,這里我們不在繼續在基礎設施里添加倉儲了,用另一種方式:IOC

項目引用Autofac,用依賴出入來初始化IRepository<T>接口

 

測試倉儲功能

復制代碼
 1 [TestClass]
 2     public class DapperRepositoryTest
 3     {
 4         private IRepository<LoginUser> repository;
 5 
 6         public DapperRepositoryTest()
 7         {
 8             var builder = new ContainerBuilder();
 9             builder.RegisterType<DapperRepository<LoginUser>>().As<IRepository<LoginUser>>();
10 
11             var container = builder.Build();
12             repository = container.Resolve<IRepository<LoginUser>>();
13         }
14 
15         [TestMethod]
16         public void Add()
17         {
18             var loginUser = new LoginUser()
19             {
20                 Id = Guid.NewGuid(),
21                 LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
22                 Password = "mima1987",
23                 IsEnabled = 1,
24                 CreateTime = DateTime.Now
25             };
26 
27             repository.Add(loginUser);
28 
29             long count = repository.Count(t => t.LoginName == loginUser.LoginName);
30 
31             Assert.AreEqual(true, count == 1);
32         }
33 
34         [TestMethod]
35         public void Get()
36         {
37             var loginUser = new LoginUser()
38             {
39                 Id = Guid.NewGuid(),
40                 LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
41                 Password = "mima1987",
42                 IsEnabled = 1,
43                 CreateTime = DateTime.Now
44             };
45             repository.Add(loginUser);
46 
47             var tmp = repository.Get(loginUser.Id);
48             Assert.AreEqual(loginUser.Id, tmp.Id);
49 
50             var tmp2 = repository.Get(w => w.Id == loginUser.Id && w.IsEnabled == loginUser.IsEnabled);
51             Assert.AreEqual(loginUser.Id, tmp2.Id);
52         }
53         ...//限於篇幅,只寫這么多了,大部分代碼都差不多
54     }
復制代碼

 

注意這句:container.Resolve<IRepository<LoginUser>>(); 這句就是實現初始化IRepository<T>接口;

如何初始化呢?看上一句:builder.RegisterType<DapperRepository<LoginUser>>().As<IRepository<LoginUser>>(); 直接注冊DapperRepository就可以了

其實這里也可以用配置的方式初始化IRepository<T>,這樣就可以避免DapperRepository<T>與業務層耦合了

測試項目,我們就暫且這么寫吧。

 

我們來看看效果

 

下邊都是這次測試生成的數據

 

自此 IRepository 就開發完成了

 

項目架構開發系列

 

 
分類:  架構設計


免責聲明!

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



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