我正在尝试使用EF 6在两个不同的DB上下文对象之间共享连接。 我有这里提到的代码 https://msdn.microsoft.com/en-us/data/dn456843.aspx 为单个数据库上下文工作,但只要我尝试与另一个数据库上下文对象共享连接,我就遇到了麻烦。以下是我为此所做的事情。
public class MyUnitOfWork
{
// BAD CODE : having static connection / transaction is bad design , i use DI to implement this properly without need for static fields , this code is used here to avoid having to mention my DI configuration;
public static EntityConnection _commonConnection ;
public static System.Data.Entity.DbContextTransaction _commonTransaction;
// Generic function to create DBContext object based on T supplied.
public static T GetDbContext<T>()
{
if(_commonConnection == null)
{
// generates a generic connection string
_commonConnection = new EntityConnection(DbContextBase.GenerateConnectionString());
_connection.Open();
_commonTransaction = _connection.BeginTransaction(System.Data.IsolationLevel.Snapshot);
}
T myContextObject = (T)Activator.CreateInstance(typeof(T), new object[1] { _connection });
myContextObject .Database.UseTransaction(_transaction);
return myContextObject;
}
}
生成连接字符串的代码如下:
string GenerateConnectionString()
{
var entityBuilder = new EntityConnectionStringBuilder
{
Provider = "System.Data.SqlClient",
ProviderConnectionString = SharedDatabase.SQLBase.DBconnection + "multipleactiveresultsets=True;" ,
Metadata = @"res://*/;"
};
return entityBuilder ;
}
然后我可以从我的函数中的不同位置调用GetDbContext,如此
GetById(int id)
{
var dbcontext = MyUnitOfWork.GetDbContext<OrdersDbContext>();
return dbcontext.Orders.Where(.......);
}
GetCustomerInfo( int id)
{
var dbcontext = MyUnitOfWork.GetDbContext<CustomerDbContext>();
return dbcontext.Customer.Where(.......);
}
因为我正在使用通用元数据部分,所以我在实体框架中遇到错误“无论命名空间如何,都不能有多个具有相同名称的实体”
但是,如果我指定.csdl / .ssdl文件的名称,连接(以及事务)就不再常见了,我必须为每个DBContext创建一个连接和事务(这是我想要的避免)
似乎我遇到了障碍。有没有办法让我使用相同的连接而不会出现重复的实体错误?将实体名称更改为不同的选项对我来说不是一个选项,因为这将是一个非常耗时的更改,我必须在30 + db上下文/ EDMX文件中进行这些更改,并产生巨大的生产影响。
答案 0 :(得分:3)
如Working with Transactions (EF6 Onwards),所示,使用以下代码为您的上下文提供现有事务:
string GenerateConnectionString()
{
return SharedDatabase.SQLBase.DBconnection + "multipleactiveresultsets=True;";
}
public class MyUnitOfWork
{
SqlConnection _commonConnection;
DbTransaction _commonTransaction;
// Generic function to create DBContext object based on T supplied.
public T GetDbContext<T>()
{
if (_commonConnection == null)
{
// generates a generic connection string
_commonConnection = new SqlConnection(DbContextBase.GenerateConnectionString());
_commonConnection.Open();
_commonTransaction = _connection.BeginTransaction(IsolationLevel.Snapshot);
}
MetadataWorkspace workspace = new MetadataWorkspace(
string.Format("res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl;", typeof(T).Name).Split('|'),
new Assembly[] { Assembly.GetExecutingAssembly() });
var connection = new EntityConnection(workspace, _commonConnection);
T myContextObject = (T)Activator.CreateInstance(typeof(T), new object[] { connection });
myContextObject.Database.UseTransaction(_commonTransaction);
return myContextObject;
}
}