日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET Core开发实战(第28课:工作单元模式(UnitOfWork):管理好你的事务)--学习笔记...

發布時間:2023/12/4 asp.net 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET Core开发实战(第28课:工作单元模式(UnitOfWork):管理好你的事务)--学习笔记... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

28 | 工作單元模式(UnitOfWork):管理好你的事務

工作單元模式有如下幾個特性:

1、使用同一上下文

2、跟蹤實體的狀態

3、保障事務一致性

我們對實體的操作,最終的狀態都是應該如實保存到我們的存儲中,進行持久化

接下來看一下代碼

為了實現工作單元模式,這里定義了一個工作單元的接口

public interface IUnitOfWork : IDisposable {Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default); }

這兩個方法的區別是:一個是返回的 int 是指我們影響的數據條數,另外一個返回 bool 表示我們保存是否成功,本質上這兩個方法達到的效果是相同的

另外還定義了一個事務管理的接口

public interface ITransaction {// 獲取當前事務IDbContextTransaction GetCurrentTransaction();// 判斷當前事務是否開啟bool HasActiveTransaction { get; }// 開啟事務Task<IDbContextTransaction> BeginTransactionAsync();// 提交事務Task CommitTransactionAsync(IDbContextTransaction transaction);// 事務回滾void RollbackTransaction(); }

在實現上我們是借助 EF 來實現工作單元模式的

看一下 EFContext 的定義

/// <summary> /// DbContext 是 EF 的基類,然后實現了 UnitOfWork 的接口和事務的接口 /// </summary> public class EFContext : DbContext, IUnitOfWork, ITransaction {protected IMediator _mediator;ICapPublisher _capBus;// 后面的章節會詳細講到這兩個參數public EFContext(DbContextOptions options, IMediator mediator, ICapPublisher capBus) : base(options){_mediator = mediator;_capBus = capBus;}#region IUnitOfWorkpublic async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default){var result = await base.SaveChangesAsync(cancellationToken);//await _mediator.DispatchDomainEventsAsync(this);return true;}可以看到這個方法實際上與上面的方法是相同的,所以這個方法可以不實現//public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)//{// return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);//}#endregion#region ITransactionprivate IDbContextTransaction _currentTransaction;// 把當前的事務用一個字段存儲public IDbContextTransaction GetCurrentTransaction() => _currentTransaction;// 獲取當前的事務就是返回存儲的私有對象public bool HasActiveTransaction => _currentTransaction != null;// 事務是否開啟是判斷當前這個事務是否為空/// <summary>/// 開啟事務/// </summary>/// <returns></returns>public Task<IDbContextTransaction> BeginTransactionAsync(){if (_currentTransaction != null) return null;_currentTransaction = Database.BeginTransaction(_capBus, autoCommit: false);return Task.FromResult(_currentTransaction);}/// <summary>/// 提交事務/// </summary>/// <param name="transaction">當前事務</param>/// <returns></returns>public async Task CommitTransactionAsync(IDbContextTransaction transaction){if (transaction == null) throw new ArgumentNullException(nameof(transaction));if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current");try{await SaveChangesAsync();// 將當前所有的變更都保存到數據庫transaction.Commit();}catch{RollbackTransaction();throw;}finally{if (_currentTransaction != null){// 最終需要把當前事務進行釋放,并且置為空// 這樣就可以多次的開啟事務和提交事務_currentTransaction.Dispose();_currentTransaction = null;}}}/// <summary>/// 回滾/// </summary>public void RollbackTransaction(){try{_currentTransaction?.Rollback();}finally{if (_currentTransaction != null){_currentTransaction.Dispose();_currentTransaction = null;}}}#endregion }

另外一個我們還是需要關注的一點就是如何管理我們的事務

這里有一個類 TransactionBehavior,這個類是用來注入我們的事務的管理過程的,具體它是怎么工作的在后續的章節會講到,這里先關注它的實現過程

public class TransactionBehavior<TDbContext, TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TDbContext : EFContext {ILogger _logger;TDbContext _dbContext;ICapPublisher _capBus;public TransactionBehavior(TDbContext dbContext, ICapPublisher capBus, ILogger logger){_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));_capBus = capBus ?? throw new ArgumentNullException(nameof(capBus));_logger = logger ?? throw new ArgumentNullException(nameof(logger));}public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next){var response = default(TResponse);var typeName = request.GetGenericTypeName();try{// 首先判斷當前是否有開啟事務if (_dbContext.HasActiveTransaction){return await next();}// 定義了一個數據庫操作執行的策略,比如說可以在里面嵌入一些重試的邏輯,這里創建了一個默認的策略var strategy = _dbContext.Database.CreateExecutionStrategy();await strategy.ExecuteAsync(async () =>{Guid transactionId;using (var transaction = await _dbContext.BeginTransactionAsync())using (_logger.BeginScope("TransactionContext:{TransactionId}", transaction.TransactionId)){_logger.LogInformation("----- 開始事務 {TransactionId} ({@Command})", transaction.TransactionId, typeName, request);response = await next();// next 實際上是指我們的后續操作,這里的模式有點像之前講的中間件模式_logger.LogInformation("----- 提交事務 {TransactionId} {CommandName}", transaction.TransactionId, typeName);await _dbContext.CommitTransactionAsync(transaction);transactionId = transaction.TransactionId;}});return response;}catch (Exception ex){_logger.LogError(ex, "處理事務出錯 {CommandName} ({@Command})", typeName, request);throw;}} }

回過頭來看一下我們的 EFContext,EFContext 實現 IUnitOfWork,工作單元模式的核心,它實現了事務的管理和工作單元模式,我們就可以借助 EFContext 來實現我們的倉儲層

總結

以上是生活随笔為你收集整理的.NET Core开发实战(第28课:工作单元模式(UnitOfWork):管理好你的事务)--学习笔记...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。