Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SaveChangesAsync(bool ensureAutoHistory = false, params IUnitOfWork[] unitOfWorks)这个怎么使用 #122

Open
panda-big opened this issue Nov 28, 2019 · 13 comments

Comments

@panda-big
Copy link
Contributor

SaveChangesAsync(bool ensureAutoHistory = false, params IUnitOfWork[] unitOfWorks)
这个怎么使用?

我这边直接传IIUnitOfWork 报错:

TransactionScope必须在同一创建线程上

@rigofunc
Copy link
Member

什么应用程序?web还是wpf?如果是web的话,默认每个就是Request Scope的呀

@panda-big
Copy link
Contributor Author

panda-big commented Dec 3, 2019

是web,我有2个上下文对象是不同数据库的,例如:
private readonly IUnitOfWork<BusinessDbContext> _businessUnitOfWork; private readonly IUnitOfWork<SysManageDbContext> _sysmanageUnitOfWork; private readonly IConfiguration Configuration; public HomeService(IUnitOfWork<BusinessDbContext> businessUnitOfWork, IUnitOfWork<SysManageDbContext> sysmanageUnitOfWork, IConfiguration configuration) { _businessUnitOfWork = businessUnitOfWork; _sysmanageUnitOfWork = sysmanageUnitOfWork; Configuration = configuration; }
当我把 _businessUnitOfWork 和 _sysmanageUnitOfWork 放进数组进行保存的时候 就会报错。

@panda-big
Copy link
Contributor Author

//add UnitOfWork
services.AddUnitOfWork<SysManageDbContext, BusinessDbContext>()

@rigofunc
Copy link
Member

rigofunc commented Dec 3, 2019

数据库是不同机器还是相同机器上的?

@panda-big
Copy link
Contributor Author

panda-big commented Dec 10, 2019

是不同机器上的mysql数据库,我查了相关资料是因为使用了 await 的问题,需要如下使用:

using(var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
//todo
}

加上这个测试之后发现 还是报错,错误如下:
Microsoft.EntityFrameworkCore.Update[10000]
An exception occurred in the database while saving changes for context type 'Infrastructure.BusinessRepository.BusinessDbContext'.
System.InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning: An ambient transaction has been detected. The current provider does not support ambient transactions. See http://go.microsoft.com/fwlink/?LinkId=800142'. This exception can be suppressed or logged by passing event ID 'RelationalEventId.AmbientTransactionWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition.Log[TLoggerCategory](IDiagnosticsLogger1 logger, WarningBehavior warningBehavior, Exception exception) at Microsoft.EntityFrameworkCore.Internal.RelationalLoggerExtensions.AmbientTransactionWarning(IDiagnosticsLogger1 diagnostics, IRelationalConnection connection, DateTimeOffset startDate)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.HandleAmbientTransactions()
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple2 parameters, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 operation, Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
System.InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning: An ambient transaction has been detected. The current provider does not support ambient transactions. See http://go.microsoft.com/fwlink/?LinkId=800142'. This exception can be suppressed or logged by passing event ID 'RelationalEventId.AmbientTransactionWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition.Log[TLoggerCategory](IDiagnosticsLogger1 logger, WarningBehavior warningBehavior, Exception exception) at Microsoft.EntityFrameworkCore.Internal.RelationalLoggerExtensions.AmbientTransactionWarning(IDiagnosticsLogger1 diagnostics, IRelationalConnection connection, DateTimeOffset startDate)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.HandleAmbientTransactions()
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple2 parameters, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 operation, Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

也就是说在.net core 里面已经不能使用TransactionScope 作为分布式事务的解决方案。
我也查看了相关资料说从.NET core 2.1 开始已经不再支持分布式事务因为移除了windows的 mstsc 远程。
所以这段代码的意义也就不存在了:
///


/// Saves all changes made in this context to the database with distributed transaction.
///

/// True if save changes ensure auto record the change history.
/// An optional array.
/// A that represents the asynchronous save operation. The task result contains the number of state entities written to database.
public async Task SaveChangesAsync(bool ensureAutoHistory = false, params IUnitOfWork[] unitOfWorks)
{
using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var count = 0;
foreach (var unitOfWork in unitOfWorks)
{
count += await unitOfWork.SaveChangesAsync(ensureAutoHistory);
}

            count += await SaveChangesAsync(ensureAutoHistory);

            ts.Complete();

            return count;
        }
    }

@panda-big
Copy link
Contributor Author

目前框架就不支持分布式事务了

@rigofunc
Copy link
Member

应该就是这个原因了,我已经几年没有写C#了,囧

@panda-big
Copy link
Contributor Author

现在搞java了?

@panda-big
Copy link
Contributor Author

panda-big commented Dec 11, 2019

我有个想法 想把查询表达式的条件封装类集成进来 达到可以根据自己组装条件的效果,例如:
//构造查询表达式
var PredicateBuilder = PredicateBuilder.Instance;
PredicateWrap expression = null;
if (!string.IsNullOrEmpty(roleRequestModel.StartTime))
{
expression &= PredicateBuilder.Equal(p => p.StartTime, Convert.ToDateTime(roleRequestModel.StartTime));
}
if (!string.IsNullOrEmpty(roleRequestModel.EndTime))
{
expression &= PredicateBuilder.Equal(p => p.EndTime, Convert.ToDateTime(roleRequestModel.EndTime));
}
list = await repository.GetPagedListAsync(
predicate: expression,
orderBy: a => a.OrderByDescending(b => b.CreateTime),
pageIndex: roleRequestModel.PageCurrent,
pageSize: roleRequestModel.PageSize);

@rigofunc
Copy link
Member

你可以提交一个PR,我看一下

@panda-big
Copy link
Contributor Author

后续 我抽时间去弄,因为 我已经在我的项目里面用了,提交了我在告诉你。

@tanher
Copy link

tanher commented Jun 29, 2021

所以这个问题不解决了吗?现在代码还是没变,但 .net core 已经到 5.0 了,现在还在报错: A TransactionScope must be disposed on the same thread that it was created.

@panda-big
Copy link
Contributor Author

这个分布式事务,在core里面已经不能使用了。我是下载的源代码去掉了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants