在长时间运行的批处理事务中,主要使用直接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
属性。
你知道如何处理这种情况吗?
答案 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