使用 EF6,如何全局设置事务隔离级别等连接属性?
With EF6, how do I globally set connection properties such as transaction isolation level?
使用 Entity Framework 6、如何为 EF 打开的每个连接设置连接属性?例如,如果我想覆盖默认的事务隔离级别。某些属性(如事务隔离级别)无法使用连接字符串进行配置。
在找到有效的解决方案之前,我尝试了几种不同的方法,但均无效。不起作用的是:
失败 #1:在 DbContext
的工厂方法中,我调用 DbContext.Database.ExecuteSql
来设置连接的属性。 失败,因为 EF 在用于其他调用之前重置了连接。
失败 #2:使用 TransactionScope
或 DbContext.Database.BeginTransaction
覆盖 DbContext.SaveChanges
和 DbContext.SaveChangesAsync
以将保存包装在具有指定隔离级别的事务中。这适用于保存更改,特别适用于隔离级别,但对查询或非隔离级别连接设置没有帮助。
失败 #3:添加了一个 IDbTransactionInterceptor
并实现了 IsolationLevelGetting
和 IsolationLevelGot
但这些似乎只能改变当您查询事务隔离时返回的隔离级别级别在 EF 代码之外。 EF代码在创建交易时不使用这个。
成功:
实施 IDbConnectionInterceptor
,实施 Opened
,我在打开的连接上执行命令,在本例中是设置事务隔离级别。这影响了 EF 执行的每个命令,使用 SQL Profiler 确认。
步骤:
创建 System.Data.Entity.Infrastructure.Interception.IDbConnectionInterceptor
的实现
public class ConnectionIsolationLevelInterceptor: IDbConnectionInterceptor
{
// Have empty implementations for all unused IDbConnectionInterceptor methods
public void BeganTransaction(DbConnection connection, BeginTransactionInterceptionContext interceptionContext)
{
}
...
... all other unused methods
...
public void Opened(DbConnection connection, DbConnectionInterceptionContext interceptionContext)
{
using (DbCommand command = connection.CreateCommand())
{
command.CommandText = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
command.ExecuteNonQuery();
}
}
}
在应用程序初始化代码中,添加拦截器:
DbInterception.Add(new ConnectionIsolationLevelInterceptor());
旁注:有许多不同的拦截器。引用 EF 6 source code 是理解它们的最佳方式。 DbInterception.Add
静态方法是查找不同类型拦截器的良好起点。 Find All References on different dispatcher methods 显示拦截器的使用位置。
使用 Entity Framework 6、如何为 EF 打开的每个连接设置连接属性?例如,如果我想覆盖默认的事务隔离级别。某些属性(如事务隔离级别)无法使用连接字符串进行配置。
在找到有效的解决方案之前,我尝试了几种不同的方法,但均无效。不起作用的是:
失败 #1:在 DbContext
的工厂方法中,我调用 DbContext.Database.ExecuteSql
来设置连接的属性。 失败,因为 EF 在用于其他调用之前重置了连接。
失败 #2:使用 TransactionScope
或 DbContext.Database.BeginTransaction
覆盖 DbContext.SaveChanges
和 DbContext.SaveChangesAsync
以将保存包装在具有指定隔离级别的事务中。这适用于保存更改,特别适用于隔离级别,但对查询或非隔离级别连接设置没有帮助。
失败 #3:添加了一个 IDbTransactionInterceptor
并实现了 IsolationLevelGetting
和 IsolationLevelGot
但这些似乎只能改变当您查询事务隔离时返回的隔离级别级别在 EF 代码之外。 EF代码在创建交易时不使用这个。
成功:
实施 IDbConnectionInterceptor
,实施 Opened
,我在打开的连接上执行命令,在本例中是设置事务隔离级别。这影响了 EF 执行的每个命令,使用 SQL Profiler 确认。
步骤:
创建 System.Data.Entity.Infrastructure.Interception.IDbConnectionInterceptor
public class ConnectionIsolationLevelInterceptor: IDbConnectionInterceptor
{
// Have empty implementations for all unused IDbConnectionInterceptor methods
public void BeganTransaction(DbConnection connection, BeginTransactionInterceptionContext interceptionContext)
{
}
...
... all other unused methods
...
public void Opened(DbConnection connection, DbConnectionInterceptionContext interceptionContext)
{
using (DbCommand command = connection.CreateCommand())
{
command.CommandText = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
command.ExecuteNonQuery();
}
}
}
在应用程序初始化代码中,添加拦截器:
DbInterception.Add(new ConnectionIsolationLevelInterceptor());
旁注:有许多不同的拦截器。引用 EF 6 source code 是理解它们的最佳方式。 DbInterception.Add
静态方法是查找不同类型拦截器的良好起点。 Find All References on different dispatcher methods 显示拦截器的使用位置。