Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework ExecuteReader要求该命令具有事务_Entity Framework_Entity Framework 6 - Fatal编程技术网

Entity framework ExecuteReader要求该命令具有事务

Entity framework ExecuteReader要求该命令具有事务,entity-framework,entity-framework-6,Entity Framework,Entity Framework 6,将事务传递给EF时,我们会遇到一个奇怪的异常: 引发异常:中的“System.InvalidOperationException” System.Data.dll 附加信息:ExecuteReader要求命令具有 当分配给命令的连接处于 待处理的本地事务。命令的事务属性 尚未初始化 然后此方法在支持EF的类中被覆盖: public override void Open(System.Data.IsolationLevel isolation, string user) { if (iso

将事务传递给EF时,我们会遇到一个奇怪的异常:

引发异常:中的“System.InvalidOperationException” System.Data.dll

附加信息:ExecuteReader要求命令具有 当分配给命令的连接处于 待处理的本地事务。命令的事务属性 尚未初始化

然后此方法在支持EF的类中被覆盖:

public override void Open(System.Data.IsolationLevel isolation, string user)
{
    if (isolation == System.Data.IsolationLevel.Unspecified)
    {
        throw new InvalidOperationException("Isolation level 'Unspecified' is not supported");
    }
    base.Open(isolation, user);
    this.DbContext = this.DbContextFactory.CreateContext<TContext>(this.Connection);
    this.DbContext.Database.UseTransaction(this.Transaction);
}
首次访问下划线ObjectContext时出现问题,试图设置事务访问基础上下文。使用TransactionScope是可以的;此问题出现在使用已与本地事务关联的连接时

虽然有点难看,但像下面这样的方法确实可以解决这个问题。具体的实现细节,如确定notCreateYet,留作练习

if (notCreatedYet)
{
    // Create a second session/connection to not touch the incoming connection.
    // Using a TransactionScope works and proper enlistment is done.
    // Attempts to open a manual transaction prior to creation will fail.
    using (new TransactionScope(TransactionScopeOption.RequiresNew))
    using (var initConn = new SqlConnection(connection.ConnectionString))
    {
        initConn.Open();
        var tempContext = this.DbContextFactory.CreateContext<TContext>(connection);
        // Touch the object context.
        if (tempContext is IObjectContextAdapter contextAdapter)
        {
            _ = contextAdapter.ObjectContext;
        }
    }
}

// Then later on this is fine.
this.DbContext = this.DbContextFactory.CreateContext<TContext>(connection);
this.DbContext.Database.UseTransaction(transaction);
首次访问下划线ObjectContext时出现问题,试图设置事务访问基础上下文。使用TransactionScope是可以的;此问题出现在使用已与本地事务关联的连接时

虽然有点难看,但像下面这样的方法确实可以解决这个问题。具体的实现细节,如确定notCreateYet,留作练习

if (notCreatedYet)
{
    // Create a second session/connection to not touch the incoming connection.
    // Using a TransactionScope works and proper enlistment is done.
    // Attempts to open a manual transaction prior to creation will fail.
    using (new TransactionScope(TransactionScopeOption.RequiresNew))
    using (var initConn = new SqlConnection(connection.ConnectionString))
    {
        initConn.Open();
        var tempContext = this.DbContextFactory.CreateContext<TContext>(connection);
        // Touch the object context.
        if (tempContext is IObjectContextAdapter contextAdapter)
        {
            _ = contextAdapter.ObjectContext;
        }
    }
}

// Then later on this is fine.
this.DbContext = this.DbContextFactory.CreateContext<TContext>(connection);
this.DbContext.Database.UseTransaction(transaction);

在初始化过程中,DdContext将确定SQL Server的版本。此进程将尝试连接到基础服务器,并使用提供的连接将select cast serverproperty“EngineEdition”查询为int,如果没有,则从配置的connectionstring创建一个新连接

这只会在第一次初始化后发生一次

因此,如果在应用程序生命周期中首次使用DbContext是在事务中,这将导致DbContext尝试使用此连接并导致观察到的错误

如果您确保第一次非事务性地调用DbContext DbContext构造和使用以进行查询,您将避免这种行为

    private static object _syncRoot = new object();
    private static bool _Initialized = false;

    private MyDbContext(string connectionString) : base(connectionString)
    {
        Database.SetInitializer<MyDbContext>(null);
    }

    private MyDbContext(DbTransaction dbTransaction) : base(dbTransaction.Connection, false)
    {
        Database.SetInitializer<MyDbContext>(null);
        Database.UseTransaction(dbTransaction);
    }

    public static MyDbContext Factory()
    {
        return new MyDbContext(Tools.GetDefaultConnectionString());
    }

    public static MyDbContext Factory(DbTransaction dbTransaction)
    {
        if(_Initialized==false)
        {
            lock(_syncRoot)
            {
                if(_Initialized==false)
                {
                    using (MyDbContext tempDbContext = new MyDbContext(dbTransaction.Connection.ConnectionString))
                    using (System.Data.Common.DbTransaction temptransaction = tempDbContext.BeginTransaction())
                    {
                        var mySampleData = tempDbContext.OneRowTable.AsNoTracking().ToList();
                        temptransaction.Commit();
                        _Initialized = true;
                    }
                }
            }
        }
        MyDbContext finalContext = new MyDbContext(dbTransaction);
        return finalContext;
    }

这是一种解决方案,适用于您不能或不想在软件中使用TransactionScope的情况。

在初始化过程中,DdContext将确定SQL Server的版本。此进程将尝试连接到基础服务器,并使用提供的连接将select cast serverproperty“EngineEdition”查询为int,如果没有,则从配置的connectionstring创建一个新连接

这只会在第一次初始化后发生一次

因此,如果在应用程序生命周期中首次使用DbContext是在事务中,这将导致DbContext尝试使用此连接并导致观察到的错误

如果您确保第一次非事务性地调用DbContext DbContext构造和使用以进行查询,您将避免这种行为

    private static object _syncRoot = new object();
    private static bool _Initialized = false;

    private MyDbContext(string connectionString) : base(connectionString)
    {
        Database.SetInitializer<MyDbContext>(null);
    }

    private MyDbContext(DbTransaction dbTransaction) : base(dbTransaction.Connection, false)
    {
        Database.SetInitializer<MyDbContext>(null);
        Database.UseTransaction(dbTransaction);
    }

    public static MyDbContext Factory()
    {
        return new MyDbContext(Tools.GetDefaultConnectionString());
    }

    public static MyDbContext Factory(DbTransaction dbTransaction)
    {
        if(_Initialized==false)
        {
            lock(_syncRoot)
            {
                if(_Initialized==false)
                {
                    using (MyDbContext tempDbContext = new MyDbContext(dbTransaction.Connection.ConnectionString))
                    using (System.Data.Common.DbTransaction temptransaction = tempDbContext.BeginTransaction())
                    {
                        var mySampleData = tempDbContext.OneRowTable.AsNoTracking().ToList();
                        temptransaction.Commit();
                        _Initialized = true;
                    }
                }
            }
        }
        MyDbContext finalContext = new MyDbContext(dbTransaction);
        return finalContext;
    }

这是一个解决方案,适用于您不能或不想在软件中使用TransactionScope的情况。

您可以发布一段自定义代码来调用EF吗?特别要注意查询数据库时使用的任何封闭using块。@ZoranHorvat此异常在this.DbContext.database.UseTransactiontransaction内抛出;此时我们不查询数据库。只是在“session”对象中实例化上下文。但是您要传递的事务对象是什么?它是从哪里来的?顺便说一句,也许你刚刚在这里偶然发现了一个EF bug。这引起了我的注意,您在真正使用DbContext做任何事情之前打开了事务。在调用UseTransation之前,您是否有办法构建模型?您可以将编译后的模型传递给DbContext,并且仅在调用UseTransation之后。这可以解决这个问题。您可以参考这篇文章,它告诉您如何在创建DbContext实例之前编译模型:您可以发布一段调用EF的自定义代码吗?特别要注意查询数据库时使用的任何封闭using块。@ZoranHorvat此异常在this.DbContext.database.UseTransactiontransaction内抛出;此时我们不查询数据库。只是在“session”对象中实例化上下文。但是您要传递的事务对象是什么?它是从哪里来的?顺便说一句,也许你刚刚在这里偶然发现了一个EF bug。这引起了我的注意,您在真正使用DbContext做任何事情之前打开了事务。在调用UseTransation之前,您是否有办法构建模型?您可以将编译后的模型传递给DbContext,并且仅在调用UseTransation之后。这可以解决这个问题。您可以参考本文,它告诉您如何在创建DbContext实例之前编译模型:
    private static object _syncRoot = new object();
    private static bool _Initialized = false;

    private MyDbContext(string connectionString) : base(connectionString)
    {
        Database.SetInitializer<MyDbContext>(null);
    }

    private MyDbContext(DbTransaction dbTransaction) : base(dbTransaction.Connection, false)
    {
        Database.SetInitializer<MyDbContext>(null);
        Database.UseTransaction(dbTransaction);
    }

    public static MyDbContext Factory()
    {
        return new MyDbContext(Tools.GetDefaultConnectionString());
    }

    public static MyDbContext Factory(DbTransaction dbTransaction)
    {
        if(_Initialized==false)
        {
            lock(_syncRoot)
            {
                if(_Initialized==false)
                {
                    using (MyDbContext tempDbContext = new MyDbContext(dbTransaction.Connection.ConnectionString))
                    using (System.Data.Common.DbTransaction temptransaction = tempDbContext.BeginTransaction())
                    {
                        var mySampleData = tempDbContext.OneRowTable.AsNoTracking().ToList();
                        temptransaction.Commit();
                        _Initialized = true;
                    }
                }
            }
        }
        MyDbContext finalContext = new MyDbContext(dbTransaction);
        return finalContext;
    }