EF Core 2.0 TransactionScope 错误
EF Core 2.0 TransactionScope Error
我正在尝试在 EntityFramework Core 2.0 的 SELECT 查询中使用 TransactionScope。但是我收到此错误:"Enlisting in Ambient transactions is not supported."
我的想法是在执行 select 查询时实施 "NO LOCK" 选项(我知道使用该选项不是一个好主意,但这是供应商的要求)。所以我加了一个扩展方法(Entity Framework with NOLOCK)
public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query)
{
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
}, TransactionScopeAsyncFlowOption.Enabled))
{
var result = await query.ToListAsync();
scope.Complete();
return result;
}
}
而且我还设置了忽略环境事务警告。
public static void AddEntityFramework(this IServiceCollection services, string connectionString)
{
services.AddDbContextPool<OptomateContext>(options =>
{
options.UseSqlServer(connectionString);
options.ConfigureWarnings(x => x.Ignore(RelationalEventId.AmbientTransactionWarning));
});
}
我的存储库中有如下查询
public async Task<Patient> GetPatient(Common.Resources.Patient patient)
{
var pat = await Dbset.Where(x => string.Equals(x.Surname,patient.Surname,
StringComparison.CurrentCultureIgnoreCase)).ToListReadUncommittedAsync();
return pat.FirstOrDefault();
}
我了解到 .Net Core 2.0 支持 TransactionScope。但我不确定为什么会出现此异常。
知道为什么会这样吗?
System.Transactions
在 EF Core 中尚不支持。该问题由 #5595: Enable support for System.Transactions and is committed to be included in the next EF Core release 2.1. (Update: EF Core 2.1 indeed added System.Transactions support).
跟踪
到那时,如果重点是使用带有 ReadUncommitted
的事务,您可以尝试使用显式 EF Core IDbTransaction
through BeginTransaction(DatabaseFacade, IsolationLevel)
扩展方法。不幸的是,它不能像您当前的自定义扩展方法那样完全封装,并且需要传递 DbContext
实例:
public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query, DbContext context)
{
using (var transaction = await context.Database.BeginTransactionAsync(System.Data.IsolationLevel.ReadUncommitted)) {
{
var result = await query.ToListAsync();
transaction.Commit();
return result;
}
}
我找到了一个不为每个查询使用事务范围的解决方法。如果您 运行 下面的代码,ef 将对相同的服务器进程 ID 使用相同的事务隔离级别。由于服务器进程 ID 在同一请求中不会更改,因此每个请求只需调用一次就足够了。
this.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
我正在尝试在 EntityFramework Core 2.0 的 SELECT 查询中使用 TransactionScope。但是我收到此错误:"Enlisting in Ambient transactions is not supported."
我的想法是在执行 select 查询时实施 "NO LOCK" 选项(我知道使用该选项不是一个好主意,但这是供应商的要求)。所以我加了一个扩展方法(Entity Framework with NOLOCK)
public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query)
{
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
}, TransactionScopeAsyncFlowOption.Enabled))
{
var result = await query.ToListAsync();
scope.Complete();
return result;
}
}
而且我还设置了忽略环境事务警告。
public static void AddEntityFramework(this IServiceCollection services, string connectionString)
{
services.AddDbContextPool<OptomateContext>(options =>
{
options.UseSqlServer(connectionString);
options.ConfigureWarnings(x => x.Ignore(RelationalEventId.AmbientTransactionWarning));
});
}
我的存储库中有如下查询
public async Task<Patient> GetPatient(Common.Resources.Patient patient)
{
var pat = await Dbset.Where(x => string.Equals(x.Surname,patient.Surname,
StringComparison.CurrentCultureIgnoreCase)).ToListReadUncommittedAsync();
return pat.FirstOrDefault();
}
我了解到 .Net Core 2.0 支持 TransactionScope。但我不确定为什么会出现此异常。
知道为什么会这样吗?
System.Transactions
在 EF Core 中尚不支持。该问题由 #5595: Enable support for System.Transactions and is committed to be included in the next EF Core release 2.1. (Update: EF Core 2.1 indeed added System.Transactions support).
到那时,如果重点是使用带有 ReadUncommitted
的事务,您可以尝试使用显式 EF Core IDbTransaction
through BeginTransaction(DatabaseFacade, IsolationLevel)
扩展方法。不幸的是,它不能像您当前的自定义扩展方法那样完全封装,并且需要传递 DbContext
实例:
public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query, DbContext context)
{
using (var transaction = await context.Database.BeginTransactionAsync(System.Data.IsolationLevel.ReadUncommitted)) {
{
var result = await query.ToListAsync();
transaction.Commit();
return result;
}
}
我找到了一个不为每个查询使用事务范围的解决方法。如果您 运行 下面的代码,ef 将对相同的服务器进程 ID 使用相同的事务隔离级别。由于服务器进程 ID 在同一请求中不会更改,因此每个请求只需调用一次就足够了。
this.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");