我需要使用SqlConnection
来使用SqlCommand.ExecuteReader()
执行无类型的本机SQL查询。我有一个现有的DbContext实例,它由与上面的SqlConnection相同的事务中的某些EF代码使用。目前,我创建了一个新的SqlConnection,从DbContext传递连接字符串:
using (var connection = new SqlConnection(db.Database.Connection.ConnectionString))
但是,我不认为这是非常有效的,因为它使用与DB的第二个底层连接,并且因为它全部在涉及第二个数据库连接(由DbContext EF代码使用)的事务中,它促进了TX使用DTC。
我想创建一个SqlConnection
,它重用与DbContext EF代码所使用的相同的底层数据库连接。这样可以避免创建/使用第二个数据库连接,并避免使用DTC。这可能吗?这是好习惯吗?
编辑:我试过这段代码:
private List<T> UseReader<T>(DbContext db)
{
try
{
var connection = (db.Database.Connection) as SqlConnection;
connection.EnlistTransaction(Transaction.Current);
var command = connection.CreateCommand();
...
但它抱怨连接未打开。所以我把代码更改为:
private List<T> UseReader<T>(DbContext db)
{
if( db.Database.Connection.State != ConnectionState.Open )
{
db.Database.Connection.Open();
}
try
{
var connection = (db.Database.Connection) as SqlConnection;
connection.EnlistTransaction(Transaction.Current);
var command = connection.CreateCommand();
..
然后我开始收到此错误:
System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached
所以最后我尝试了这段代码:
private List<T> UseReader<T>(DbContext db)
{
var opened = false;
if( db.Database.Connection.State != ConnectionState.Open )
{
db.Database.Connection.Open();
opened = true;
}
try
{
var connection = (db.Database.Connection) as SqlConnection;
connection.EnlistTransaction(Transaction.Current);
var command = connection.CreateCommand();
...
}
finally
{
if (opened)
{
db.Database.Connection.Close();
}
}
}
但是这导致了下游EF代码中出现此错误:
The operation cannot be completed because the `DbContext` has been disposed
编辑2:解决方案 - 实际上代码的最终版本是正确的。我收到关于处置DbContext
的错误的原因是因为在我们之前的调查中,我们在下游的某处包含了SqlConnection.ClearPool()
调用,在包含connection.close()
调用后开始抛出该错误。