我有一个应用程序,可以将大量数据读入内存并批量处理。
我想要的是实体框架要忽略 DbUpdateConcurrencyException
删除已删除的实体时。
原因是,当一个实体被处理并标记为删除时,它可能已经从数据库中删除。
不经意地删除已经删除的行不是问题,不应该导致错误,我只需要一种方法告诉实体框架:)
例
Db.Entry(itemToRemove).State = EntityState.Deleted;
Db.SaveChanges();
如果导致错误 itemToRemove
已被删除。
注意: Db.Configuration.ValidateOnSaveEnabled = false;
不会像另一个线程建议那样修复此问题。
怎么样?
Db.Entry(itemToRemove).State = EntityState.Deleted;
bool saveFailed;
do
{
saveFailed = false;
try
{
Db.SaveChanges();
}
catch(DbUpdateConcurrencyException ex)
{
saveFailed = true;
var entry = ex.Entries.Single();
//The MSDN examples use Single so I think there will be only one
//but if you prefer - do it for all entries
//foreach(var entry in ex.Entries)
//{
if(entry.State == EntityState.Deleted)
//When EF deletes an item its state is set to Detached
//http://msdn.microsoft.com/en-us/data/jj592676.aspx
entry.State = EntityState.Detached;
else
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
//throw; //You may prefer not to resolve when updating
//}
}
} while (saveFailed);
更多信息:
解决乐观并发异常
怎么样?
Db.Entry(itemToRemove).State = EntityState.Deleted;
bool saveFailed;
do
{
saveFailed = false;
try
{
Db.SaveChanges();
}
catch(DbUpdateConcurrencyException ex)
{
saveFailed = true;
var entry = ex.Entries.Single();
//The MSDN examples use Single so I think there will be only one
//but if you prefer - do it for all entries
//foreach(var entry in ex.Entries)
//{
if(entry.State == EntityState.Deleted)
//When EF deletes an item its state is set to Detached
//http://msdn.microsoft.com/en-us/data/jj592676.aspx
entry.State = EntityState.Detached;
else
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
//throw; //You may prefer not to resolve when updating
//}
}
} while (saveFailed);
更多信息:
解决乐观并发异常
你可以处理 DbUpdateConcurrencyException
然后打电话 Refresh(RefreshMode,IEnumerable)
使用RefreshMode.StoreWins和已删除的实体作为参数。
try{
Db.Entry(itemToRemove).State = EntityState.Deleted;
Db.SaveChanges();
}
catch(DbUpdateConcurrencyException)
{
IObjectContextAdapter adapter = Db;
adapter.ObjectContext.Refresh(RefreshMode.StoreWins, context.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Deleted));
Db.SaveChanges();
}
基于来自的代码 https://msdn.microsoft.com/en-US/data/jj592904 但是我添加了一个infite循环计数器(以防万一,你永远不知道,对吧?)并循环遍历异常列表中的所有条目。
var maxTriesCounter = 20;
bool saveFailed;
do
{
saveFailed = false;
maxTriesCounter--;
try
{
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
foreach (var entry in ex.Entries)
{
entry.Reload();
}
}
} while (saveFailed && maxTriesCounter > 0);
这是我使用的。保存后分离所有问题记录。
Db.Entry(itemToRemove).State = EntityState.Deleted;
while(true)
try {
Db.SaveChanges();
break;
} catch (DbUpdateConcurrencyException ex) {
ex.Entries.ToList().ForEach(x=>x.State=EntityState.Detached);
}
或者,您可以将自定义SaveChanges函数添加到DbContext类,并在需要忽略这些错误时使用它。
public int SaveChanges_IgnoreConcurrencyExceptions () {
while(true)
try {
return this.SaveChanges();
} catch (DbUpdateConcurrencyException ex) {
ex.Entries.ToList().ForEach(x => x.State=EntityState.Detached);
}
}