EntityCommandExecutionException如果从SqlConnection创建EF上下文

时间:2015-03-23 10:35:32

标签: c# entity-framework transactions

在长时间运行的批处理事务中,主要使用直接SQL语句运行,我想使用EF语句,该语句应该作为当前事务的一部分运行。

我查看了DbContext的构造函数,并提出了以下方法:

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ResPlannerContext"].ConnectionString))
{
    connection.Open();
    SqlTransaction trans = connection.BeginTransaction();
    using (ResPlannerContext context = new ResPlannerContext(trans.Connection, false))
    {
        var data = context.Activities.Where(x => x.StartDate < DateTime.Today);
        Console.WriteLine("Count: " + data.Count());
    }
}

好消息:汇编。坏的:弹出以下异常:

Message=An error occurred while executing the command definition. See the inner exception for details.
Source=EntityFramework
StackTrace:
   bei System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   bei System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
   bei System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
   bei System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   bei System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
   bei System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
   bei System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   bei System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
   bei System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   bei System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   bei System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3[TResult](IEnumerable`1 sequence)
   bei System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   bei System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   bei System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   bei System.Linq.Queryable.Count[TSource](IQueryable`1 source)
   bei ConsoleApplication3.Program.Main(String[] args) in c:\Users\sreindl\Documents\Visual Studio 2013\Projects\ConsoleApplication3\ConsoleApplication3\Program.cs:Zeile 26.
   bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   bei System.Threading.ThreadHelper.ThreadStart()
InnerException: System.InvalidOperationException
   _HResult=-2146233079
   _message=ExecuteReader erfordert, dass der Befehl über eine Transaktion verfügt, wenn die dem Befehl zugewiesene Verbindung eine ausstehende lokale Verbindung ist. Die Transaction-Eigenschaft des Befehls wurde nicht initialisiert.
   HResult=-2146233079
   IsTransient=false
   Message=ExecuteReader erfordert, dass der Befehl über eine Transaktion verfügt, wenn die dem Befehl zugewiesene Verbindung eine ausstehende lokale Verbindung ist. Die Transaction-Eigenschaft des Befehls wurde nicht initialisiert.
   Source=System.Data
   StackTrace:
        bei System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
        bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
        bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
        bei System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
        bei System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
        bei System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
        bei System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)
        bei System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
        bei System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
        bei System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
        bei System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
        bei System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   InnerException: 

内部的德语异常(抱歉使用德语SQL Server :-)表示:当分配给命令的连接处于挂起的本地trans时,ExecuteReader需要命令才能进行事务处理。

实际上没有设置内部SqlCommand的Transaction属性。

你知道如何处理这种情况吗?

2 个答案:

答案 0 :(得分:1)

可能如下:

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ResPlannerContext"].ConnectionString))
{
    connection.Open();
    using (ResPlannerContext context = new ResPlannerContext(connection, false))
    {
        using (var tran = context.Database.BebinTransaction() ) {
            var data = context.Activities.Where(x => x.StartDate < DateTime.Today);
            Console.WriteLine("Count: " + data.Count());

            tran.Commit();
        }
    }
}

另外,正如所述here

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ResPlannerContext"].ConnectionString))
{
    connection.Open();
    SqlTransaction trans = connection.BeginTransaction();
    using (ResPlannerContext context = new ResPlannerContext(trans.Connection, false))
    {
        context.Database.UseTransaction(trans);

        var data = context.Activities.Where(x => x.StartDate < DateTime.Today);
        Console.WriteLine("Count: " + data.Count());
    }
}

答案 1 :(得分:0)

我认为你应该为此写两个单独的交易。一个应该是连接事务和另一个SQLTransaction:

string connString = ConfigurationManager.ConnectionStrings["db"].ConnectionString;
using (var conn = new SqlConnection(connString))
{
    conn.Open();
    using (IDbTransaction tran = conn.BeginTransaction())
    {
        try
        {
            // transactional code...
            using (SqlCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = "INSERT INTO Data(Code) VALUES('A-100');";
                cmd.Transaction = tran as SqlTransaction;
                cmd.ExecuteNonQuery();
            }
            tran.Commit();
        }
        catch(Exception ex)
        {
            tran.Rollback();
            throw;
        }
    }
}

查看S.M.Ahasan Habib在以下链接中的帖子,他解释了上述代码: http://www.codeproject.com/Articles/690136/All-About-TransactionScope