日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

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

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

工作單元模式有如下幾個(gè)特性:

1、使用同一上下文

2、跟蹤實(shí)體的狀態(tài)

3、保障事務(wù)一致性

我們對(duì)實(shí)體的操作,最終的狀態(tài)都是應(yīng)該如實(shí)保存到我們的存儲(chǔ)中,進(jìn)行持久化

接下來看一下代碼

為了實(shí)現(xiàn)工作單元模式,這里定義了一個(gè)工作單元的接口

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

這兩個(gè)方法的區(qū)別是:一個(gè)是返回的 int 是指我們影響的數(shù)據(jù)條數(shù),另外一個(gè)返回 bool 表示我們保存是否成功,本質(zhì)上這兩個(gè)方法達(dá)到的效果是相同的

另外還定義了一個(gè)事務(wù)管理的接口

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

在實(shí)現(xiàn)上我們是借助 EF 來實(shí)現(xiàn)工作單元模式的

看一下 EFContext 的定義

/// <summary> /// DbContext 是 EF 的基類,然后實(shí)現(xiàn)了 UnitOfWork 的接口和事務(wù)的接口 /// </summary> public class EFContext : DbContext, IUnitOfWork, ITransaction {protected IMediator _mediator;ICapPublisher _capBus;// 后面的章節(jié)會(huì)詳細(xì)講到這兩個(gè)參數(shù)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;}可以看到這個(gè)方法實(shí)際上與上面的方法是相同的,所以這個(gè)方法可以不實(shí)現(xiàn)//public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)//{// return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);//}#endregion#region ITransactionprivate IDbContextTransaction _currentTransaction;// 把當(dāng)前的事務(wù)用一個(gè)字段存儲(chǔ)public IDbContextTransaction GetCurrentTransaction() => _currentTransaction;// 獲取當(dāng)前的事務(wù)就是返回存儲(chǔ)的私有對(duì)象public bool HasActiveTransaction => _currentTransaction != null;// 事務(wù)是否開啟是判斷當(dāng)前這個(gè)事務(wù)是否為空/// <summary>/// 開啟事務(wù)/// </summary>/// <returns></returns>public Task<IDbContextTransaction> BeginTransactionAsync(){if (_currentTransaction != null) return null;_currentTransaction = Database.BeginTransaction(_capBus, autoCommit: false);return Task.FromResult(_currentTransaction);}/// <summary>/// 提交事務(wù)/// </summary>/// <param name="transaction">當(dāng)前事務(wù)</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();// 將當(dāng)前所有的變更都保存到數(shù)據(jù)庫(kù)transaction.Commit();}catch{RollbackTransaction();throw;}finally{if (_currentTransaction != null){// 最終需要把當(dāng)前事務(wù)進(jìn)行釋放,并且置為空// 這樣就可以多次的開啟事務(wù)和提交事務(wù)_currentTransaction.Dispose();_currentTransaction = null;}}}/// <summary>/// 回滾/// </summary>public void RollbackTransaction(){try{_currentTransaction?.Rollback();}finally{if (_currentTransaction != null){_currentTransaction.Dispose();_currentTransaction = null;}}}#endregion }

另外一個(gè)我們還是需要關(guān)注的一點(diǎn)就是如何管理我們的事務(wù)

這里有一個(gè)類 TransactionBehavior,這個(gè)類是用來注入我們的事務(wù)的管理過程的,具體它是怎么工作的在后續(xù)的章節(jié)會(huì)講到,這里先關(guān)注它的實(shí)現(xiàn)過程

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{// 首先判斷當(dāng)前是否有開啟事務(wù)if (_dbContext.HasActiveTransaction){return await next();}// 定義了一個(gè)數(shù)據(jù)庫(kù)操作執(zhí)行的策略,比如說可以在里面嵌入一些重試的邏輯,這里創(chuàng)建了一個(gè)默認(rèn)的策略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("----- 開始事務(wù) {TransactionId} ({@Command})", transaction.TransactionId, typeName, request);response = await next();// next 實(shí)際上是指我們的后續(xù)操作,這里的模式有點(diǎn)像之前講的中間件模式_logger.LogInformation("----- 提交事務(wù) {TransactionId} {CommandName}", transaction.TransactionId, typeName);await _dbContext.CommitTransactionAsync(transaction);transactionId = transaction.TransactionId;}});return response;}catch (Exception ex){_logger.LogError(ex, "處理事務(wù)出錯(cuò) {CommandName} ({@Command})", typeName, request);throw;}} }

回過頭來看一下我們的 EFContext,EFContext 實(shí)現(xiàn) IUnitOfWork,工作單元模式的核心,它實(shí)現(xiàn)了事務(wù)的管理和工作單元模式,我們就可以借助 EFContext 來實(shí)現(xiàn)我們的倉(cāng)儲(chǔ)層

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。