gpt4 book ai didi

c# - Hangfire 交易流程(工作单元)

转载 作者:太空宇宙 更新时间:2023-11-03 14:45:57 26 4
gpt4 key购买 nike

在下面的 .Net Framework 代码中,确保将 someEntity 对象插入到 db 中,然后执行 Publish 操作。但是,在 .Net Core 中,我无法做到这一点。当我尝试运行这段代码时,发生了平台异常。

using (var transaction = new TransactionScope())
{
SomeEntity someEntity = new SomeEntity();
someEntity.Gui = Guid.NewGuid().ToString();

_dataContext.SomeEntities.Add(someEntity);
_dataContext.SaveChanges();

_backgroundJobClient.Enqueue(() => PublishSomeEntityCreatedEvent(someEntity.Id)));

transaction.Complete();
}

对于这种情况有什么已知好的解决方案吗?

注:.Net Core 2.2 Console application、EntityFrameworkCore 2.1 和 Hangfire 1.6.21 用于测试


更新:整个堆栈跟踪

Hangfire.BackgroundJobClientException: Background job creation failed. See inner exception for details. ---> System.PlatformNotSupportedException: This platform
does not support distributed transactions.
at System.Transactions.Distributed.DistributedTransactionManager.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
at System.Transactions.TransactionInterop.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
at System.Transactions.Transaction.Promote()
at System.Transactions.TransactionInterop.ConvertToDistributedTransaction(Transaction transaction)
at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Hangfire.SqlServer.SqlServerStorage.CreateAndOpenConnection()
at Hangfire.SqlServer.SqlServerStorage.UseConnection[T](DbConnection dedicatedConnection, Func`2 func)
at Hangfire.SqlServer.SqlServerConnection.CreateExpiredJob(Job job, IDictionary`2 parameters, DateTime createdAt, TimeSpan expireIn)
at Hangfire.Client.CoreBackgroundJobFactory.Create(CreateContext context)
at Hangfire.Client.BackgroundJobFactory.<>c__DisplayClass7_0.<CreateWithFilters>b__0()
at Hangfire.Client.BackgroundJobFactory.InvokeClientFilter(IClientFilter filter, CreatingContext preContext, Func`1 continuation)
at Hangfire.Client.BackgroundJobFactory.<>c__DisplayClass7_1.<CreateWithFilters>b__2()
at Hangfire.Client.BackgroundJobFactory.CreateWithFilters(CreateContext context, IEnumerable`1 filters)
at Hangfire.Client.BackgroundJobFactory.Create(CreateContext context)
at Hangfire.BackgroundJobClient.Create(Job job, IState state)
--- End of inner exception stack trace ---
at Hangfire.BackgroundJobClient.Create(Job job, IState state)
at Hangfire.BackgroundJobClientExtensions.Create(IBackgroundJobClient client, Expression`1 methodCall, IState state)
at Hangfire.BackgroundJobClientExtensions.Enqueue(IBackgroundJobClient client, Expression`1 methodCall)
at TopShelf_Hangfire_NetCore.BusinessService.Execute(DateTime utcNow) in C:\Projects\Practices\TopShelf_Hangfire_NetCore\BusinessService.cs:line 31
at TopShelf_Hangfire_NetCore.StartupService._timer_Elapsed(Object sender, ElapsedEventArgs e) in C:\Projects\Practices\TopShelf_Hangfire_NetCore\StartupService.cs:line 35

最佳答案

现在使用 EntityFramework Core 3.0 或更高版本时可以使用。这在 EFCore 2.x 中不起作用的原因是 EFCore 2.x 在不使用时没有关闭连接。相反,DbConnection 一直保持打开状态,直到上下文被释放。

此行为在 EF Core 3.0 中已更改:https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#database-connection-is-now-closed-if-not-used-anymore-before-the-transactionscope-has-been-completed

从 3.0 开始,EF Core 在使用完后立即关闭连接。这使您的场景成为可能,您希望在同一事务中加入 EfCore 和 Hangfire,而无需升级到 MSDTC。

关于c# - Hangfire 交易流程(工作单元),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54235041/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com