从DbContext

时间:2017-03-22 20:58:31

标签: .net entity-framework sqlconnection

我需要使用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()调用后开始抛出该错误。

0 个答案:

没有答案