.NetCore中使用Dapper


Dapper是什么?

Dapper是開源的、輕量級,高性能的ORM(對象關系映射)。

Dapper的特點:

一、輕量:Dapper的GitHub地址:https://github.com/StackExchange/Dapper/tree/main/Dapper,它的核心代碼是SqlMapper.cs。代碼量不多,編輯后所占空間也比較小。

二、高性能:它通過Emit反射IDataReader的序列隊列,快速的映射出對象。

三、Dapper更傾向於面向SQL,支持多種數據庫。

 .NetCore中簡單封裝使用Dapper

1、引入Dapper和Dapper.Contrib

2、創建倉儲接口

 1 public interface IRepository<T> where T:BaseEntity
 2     {
 3         T GetById(string id);
 4         IEnumerable<T> GetAll();
 5         IEnumerable<T> GetBySql(string sql, Dictionary<string, object> parameter, CommandType commandType);
 6         IEnumerable<T> GetByPaging(string sql, Dictionary<string, object> parameters, CommandType commandType);
 7        
 8         void Add(T entity);
 9         void Delete(T entity);
10         void Update(T Entity);
11 
12     }

 

3、創建倉儲基類

 1    public class BaseRepository<T> : IRepository<T> where T : BaseEntity
 2     {
 3         private IDbConnection _connection;
 4         public BaseRepository(IConfiguration configuration)
 5         {
 6             this._connection = new MySqlConnection(configuration.GetConnectionString("ListingDb"));
 7         }
 8 
 9         public IEnumerable<T> GetAll()
10         {
11             var result = _connection.GetAll<T>();
12             return result;
13         }
14 
15         public T GetById(string id)
16         {
17             var result = _connection.Get<T>(id);
18             return result;
19         }
20 
21         public IEnumerable<T> GetByPaging(string sql, Dictionary<string, object> parameters, CommandType commandType)
22         {
23             //TODO query paging
24             return null;
25         }
26 
27         public IEnumerable<T> GetBySql(string sql, Dictionary<string, object> parameters, CommandType commandType)
28         {
29             var result = _connection.Query<T>(sql, parameters, commandType: commandType);
30             return result;
31         }
32 
33         public void Add(T entity)
34         {
35             _connection.Insert(entity, null);
36         }
37         public void Update(T entity)
38         {
39             _connection.Update(entity);
40         }
41         public void Delete(T entity)
42         {
43             _connection.Delete(entity);
44         }
45     }

4、在startup.cs中注入倉儲類

 

services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));

5、定義具體業務類進行調用(略)

 

進階--實現Dapper+UnitOfWork

想了解UOW(UnitOfWork)可參照:https://martinfowler.com/eaaCatalog/unitOfWork.html

在【簡單封裝dapper】中,不難發現它主要是針對單個對象的操作。即使通過注入多個對象的倉儲進行統一處理統一事務的多表,但是還是缺少了事務的支持。就像之前寫的關於數據庫訪問的封裝(https://www.cnblogs.com/johnyong/p/14152891.html)一樣,需要將事務進行抽離,即做成單獨的工作單元,實現對對象狀態的跟蹤,實現事務。

以下是簡單的實現

1、定義IUnitOfWork接口

1     public interface IUnitOfWork
2     {
3         Guid Id { get; }
4         IDbConnection Connection { get; }
5         IDbTransaction Transaction { get; }
6         void Begin();
7         void Commit();
8         void Rollback(); 
9     }

2、定義UnitOfWork

 1     public sealed class UnitOfWork : IUnitOfWork, IDisposable
 2     {
 3         private Guid _id = Guid.Empty;
 4         private IDbConnection _connection = null;
 5         private IDbTransaction _transaction = null;
 6         private bool _disposed = false;
 7  
 8         public UnitOfWork(IConfiguration configuration)
 9         {
10             _id = new Guid();
11             _connection = new MySqlConnection(configuration.GetConnectionString("SimpleTestConnection"));
12 
13 
14         }
15 
16 
17         public Guid Id
18         {
19             get { return _id; }
20         }
21 
22         public IDbConnection Connection
23         {
24             get { return _connection; }
25         }
26         public IDbTransaction Transaction
27         {
28             get { return _transaction; }
29         }
30 
31         public void Begin()
32         {
33             if (_connection.State != ConnectionState.Open)
34             {
35                 _connection.Open();
36             }
37             _transaction = _connection.BeginTransaction();
38         }
39 
40         public void Commit()
41         {
42             _transaction.Commit();
43             Dispose();
44         }
45 
46         public void Rollback()
47         {
48             _transaction.Rollback();
49             Dispose();
50         }
51 
52 
53         public void Dispose()
54         {
55             Dispose(true);
56             GC.SuppressFinalize(this);
57         }
58 
59         public void Dispose(bool disposing)
60         {
61             if (_disposed)
62                 return;
63 
64             if (disposing)
65             {
66                 _transaction?.Dispose();
67                 _connection?.Dispose();
68             }
69 
70             _transaction = null;
71             _connection = null;
72             _disposed = true;
73         }
74         ~UnitOfWork()
75         {
76             Dispose(false);
77         }
78     }

3、修改BaseRepository

 1     public class BaseRepository<T> : IRepository<T> where T : BaseEntity
 2     {
 3         private IUnitOfWork _unitOfWork;
 4         public BaseRepository(IUnitOfWork unitOfWork)
 5         {
 6             this._unitOfWork = unitOfWork;
 7         }
 8        
 9         public IEnumerable<T> GetAll()
10         {
11             var result = _unitOfWork.Connection.GetAll<T>();
12             return result;
13         }
14 
15         public T GetById(string id)
16         {
17             var result = _unitOfWork.Connection.Get<T>(id);
18             return result;
19         }
20 
21         public IEnumerable<T> GetByPaging(string sql, Dictionary<string, object> parameters, CommandType commandType)
22         {
23             //TODO query paging
24             return null; 
25         }
26 
27         public IEnumerable<T> GetBySql(string sql, Dictionary<string, object> parameters, CommandType commandType)
28         {
29             var result = _unitOfWork.Connection.Query<T>(sql, parameters, commandType: commandType);
30             return result;
31         }
32 
33         public void Add(T entity)
34         {
35             _unitOfWork.Connection.Insert(entity,null);
36         }
37         public void Update(T entity)
38         {
39             _unitOfWork.Connection.Update(entity);
40         }
41         public void Delete(T entity)
42         {
43             _unitOfWork.Connection.Delete(entity);
44         }
45     }

 

4、定義事務特性,用於實現aop(需要引入AspectCore.DynamicProxy)

 1     public class SystemTransactionAttribute : AbstractInterceptorAttribute
 2     {
 3         IUnitOfWork _unitOfWork { get; set; }
 4 
 5         public async override Task Invoke(AspectContext context, AspectDelegate next)
 6         {
 7             try
 8             {
 9                 _unitOfWork = context.ServiceProvider.GetService(typeof(IUnitOfWork)) as IUnitOfWork;
10                 _unitOfWork.Begin();
11                 await next(context);
12                 _unitOfWork.Commit();
13             }
14             catch (Exception ex )
15             {
16                 _unitOfWork.Rollback();
17                 throw new Exception("SystemTransaction error",ex);
18             }
19         }
20     }

 

5、注入服務

在startup.cs注入UnitOfWork

            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));

 

修改Program.cs

 1     public class Program
 2     {
 3         public static void Main(string[] args)
 4         {
 5             CreateHostBuilder(args).Build().Run();
 6         }
 7 
 8         public static IHostBuilder CreateHostBuilder(string[] args) =>
 9             Host.CreateDefaultBuilder(args)
10                 .ConfigureWebHostDefaults(webBuilder =>
11                 {
12                     webBuilder.UseStartup<Startup>();
13                 }).UseDynamicProxy();
14     }

 

6、測試示例代碼

 1     public class ListingService: IListingService
 2     {
 3         private IRepository<Listing> _listingRepository;
 4         private IRepository<ListingDetail> _listingDetailRepository;
 5 
 6         public ListingService(IRepository<Listing> listingRepository,IRepository<ListingDetail> listingDetailRepository)
 7         {
 8             this._listingRepository = listingRepository;
 9             this._listingDetailRepository = listingDetailRepository;
10         }
11         [SystemTransaction]
12         public void AddListing(ListingContract contract)
13         { 
14             var listing = new Listing()
15             {
16                 Id = ObjectId.GenerateNewId().ToString(), 
17                 Price = contract.Price,
18                 Quantity = contract.Quantity,
19                 Title=contract.Title,
20                 Remark="john_yong test"
21             };
22             _listingRepository.Add(listing);
23             foreach (var item in contract.DetailList)
24             {
25                 var listingDetail = new ListingDetail()
26                 {
27                     Id ="",//設置Id為空拋出異常 //ObjectId.GenerateNewId().ToString(),
28                     ListingId = listing.Id,
29                     Quantity = item.Quantity,
30                     SKU = item.SKU,
31                 };
32                 _listingDetailRepository.Add(listingDetail);
33             } 
34             
35         }
36     }

 

注:

使用dapper.Contrib,默認數據庫表明為實體名稱的復數形式,我們可以使用[Table]特性進行聲明表名稱。

Dapper.Contrib.Extensions擴展而言:自增主鍵用[Key]標志(默認為自增主鍵),非自增主鍵必須用[ExplicitKey]標志,否則即使我們給Id指定值再進行插入數據表,最終Id還是為空。

 

 

--------------------

本文地址: https://www.cnblogs.com/johnyong/p/14433155.html

 


免責聲明!

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



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