我已经阅读了几个关于可能导致dbUpdateConcurrencyException
的问题的文章和文章,但似乎没有一个与我的代码中发生的事情有关。我对我的CRUD操作进行了简单的功能测试,使用 Entity Framework 6.0 。
我的[TestInitialize]
会插入一些数据,而我的[TestCleanup]
会删除相同的数据。除了删除记录的测试之外,这适用于我的所有测试。当调用该测试的清理时,它会抛出dbUpdateConcurrencyException
。
我的测试清理方法就是这样:
var contracts = this.Context.Contract
.Where(c => c.EntryUserID == "FunctionalTests.TestData").ToList();
this.Context.Contract.RemoveRange(contracts);
this.Context.SaveChanges();
var customers = this.Context.Customer
.Where(c => c.EntryUserID == "FunctionalTests.TestData").ToList();
this.Context.Customer.RemoveRange(customers);
this.Context.SaveChanges(); //This throws dbUpdateConcurrencyException??
在此失败之前运行的测试将从Context.Contract
中删除一条记录。一些奇怪的事情:
Context.Contract
的清理工作正常。虽然Context.Customer
是在测试期间删除的内容,但Customer.Contract
已清除Contract
。 CustomerId
确实有Customer
的外键。我猜这是相关的;删除合同将更改Customer
实体,因为RemoveRange()
实体具有合同集合属性。但是,在我删除合同之后我再次加载客户;所以他们在加载和删除之间被 修改。
我尝试一次删除一项而不是Reload()
;第一次删除时发生同样的错误。在尝试删除Customer
之前,我尝试在特定Customer
实体上调用2 updateFunction)
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update()
at System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesToStore>b__35()
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func
;同样的结果。
另请注意,这适用于所有其他不删除合同的测试。因此,在删除客户之前删除所有合同的工作正常。只有在删除单个合同之前,才能删除其中的剩余合同。
这是完整的错误消息/堆栈跟踪:
System.Data.Entity.Infrastructure.DbUpdateConcurrencyException:System.Data.Entity.Infrastructure.DbUpdateConcurrencyException:存储更新,插入或删除语句影响了意外的行数(0)。自实体加载后,实体可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=472540。 ---&GT; System.Data.Entity.Core.OptimisticConcurrencyException:存储更新,插入或删除语句影响了意外的行数(0)。自实体加载后,实体可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=472540。 结果StackTrace:
在System.Data.Entity.Internal.InternalContext.SaveChanges() 在System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 在System.Data.Entity.DbContext.SaveChanges()
内部异常具有完全相同的类型和消息,具有此堆栈跟踪:
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.ValidateRowsAffected(Int64 rowsAffected,UpdateCommand source) 在System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() 在System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.b__2(UpdateTranslator ut) 在System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update [T](T noChangesResult,Func
DbContext
1 func,IDbExecutionStrategy executionStrategy,Boolean startLocalTransaction,Boolean releaseConnectionOnSuccess) 在System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions选项,IDbExecutionStrategy executionStrategy,Boolean startLocalTransaction) 在System.Data.Entity.Core.Objects.ObjectContext。&lt;&gt; c__DisplayClass2a.b__27() 在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute [TResult](Func`1操作) at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options,Boolean executeInExistingTransaction) 在System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions选项) 在System.Data.Entity.Internal.InternalContext.SaveChanges()
更新
通过将我在数据设置/拆解中使用的DbContext
传递给正在测试的方法,我能够让它工作/解决它。换句话说,错误似乎是因为有一个DbContext
用于测试设置/拆卸,而另一个DbContext
用于测试的代码。
然而,这并没有真正回答我的任何问题。我宁愿不必绕过我的{{1}}来确保它是一样的;有没有办法告诉我的上下文从实际的数据库刷新/加载,而不只是使用它知道的东西?而且,这并没有解释为什么删除合同会正常工作,而且只能删除客户。
答案 0 :(得分:0)
导致此错误的原因是测试设置运行时正在加载测试设置和拆卸使用的DBContext。不同的上下文使得数据库在设置和拆卸之间发生变化,并且因为第一个上下文是在安装过程中加载的,所以它基于一个旧的&#34;数据库的版本,即测试运行之前的版本。
解决方案是没有拆卸使用与设置使用的DBContext相同的DBContext。 Teardown应加载自己的新DBContext,以便根据最新数据加载它。
我认为重要的是从数据库加载要删除的客户时的数据状态。但显然最重要的是DBContext加载时的数据状态。