删除行时如何避免乐观并发异常?
How I can avoid optimistic concurrency exception when I delete rows?
我有一个方法可以接收要删除的某些行的 ID。我正在使用这样的代码:
public bool delete(IEnumerable<long> paramIeId)
{
using(myContext)
{
foreach(long iterator in paramIeId)
{
nyDbContext.Remove(new MyType(){ID = iterator});
}
}
}
它工作正常,因为存在时删除行。但是如果区域 1 行或多行不存在,那么我会得到一个异常并且没有一行被删除,尽管其中一些存在。
如果我在 T-SQL 中执行此查询我没有问题,数据库会删除现有行并忽略不存在的行,因为最后我想删除它们所以如果另一个进程帮我删了,没问题。
我可以处理从数据库刷新 dbContext 的乐观并发异常,但我认为这是可以避免的额外查询。
EF 有什么方法可以像 T-SQL 那样工作吗?如果我尝试删除不存在的行,请忽略它并删除其余行。
谢谢。
您无需创建新对象即可删除它,只需让 EF 为您处理一切:
public bool delete(IEnumerable<long> paramIeId)
{
using(var nyDbContext = new DbContext())
{
foreach(long id in paramIeId)
{
MyType myType = nyDbContext.MyTypes.FirstOrDefault(x => x.ID == id);
if (myType != null)
{
nyDbContext.MyTypes.Remove(myType);
}
}
nyDbContext.SaveChanges();
}
}
至少目前,使用分离实体执行删除时异常似乎是不可避免的。您要么必须使用 try / catch
并处理异常,要么查询数据库以查找匹配的 ID,并且只删除匹配项 1.
异常处理示例
using (myContext)
{
foreach (long iterator in paramIeId)
{
nyDbContext.Remove(new MyType() { ID = iterator });
}
try
{
nyDbContext.SaveChanges()
}
catch(DbUpdateConcurrencyException ex)
{
//if you want special handling for double delete
}
}
样本查询然后删除
请注意,我在循环之前查询了整个类型列表,以避免对每种类型进行单独查询。
using (myContext)
{
var existingMyTypes = nyDbContext.MyTypes.Where(x => paramIeId.Contains(x.ID));
foreach (MyType existing in existingMyTypes)
{
nyDbContext.Remove(existing);
}
nyDbContext.SaveChanges();
}
1 注意:查询然后删除选项会打开一个可能的竞争条件,这可能会触发您尝试的 OptimisticConcurrencyException
- 即,如果另一个进程 /线程/程序删除您自己进程的读取和删除之间的行。完全处理这种可能性的唯一方法是在 try / catch
.
中处理异常
我有一个方法可以接收要删除的某些行的 ID。我正在使用这样的代码:
public bool delete(IEnumerable<long> paramIeId)
{
using(myContext)
{
foreach(long iterator in paramIeId)
{
nyDbContext.Remove(new MyType(){ID = iterator});
}
}
}
它工作正常,因为存在时删除行。但是如果区域 1 行或多行不存在,那么我会得到一个异常并且没有一行被删除,尽管其中一些存在。
如果我在 T-SQL 中执行此查询我没有问题,数据库会删除现有行并忽略不存在的行,因为最后我想删除它们所以如果另一个进程帮我删了,没问题。
我可以处理从数据库刷新 dbContext 的乐观并发异常,但我认为这是可以避免的额外查询。
EF 有什么方法可以像 T-SQL 那样工作吗?如果我尝试删除不存在的行,请忽略它并删除其余行。
谢谢。
您无需创建新对象即可删除它,只需让 EF 为您处理一切:
public bool delete(IEnumerable<long> paramIeId)
{
using(var nyDbContext = new DbContext())
{
foreach(long id in paramIeId)
{
MyType myType = nyDbContext.MyTypes.FirstOrDefault(x => x.ID == id);
if (myType != null)
{
nyDbContext.MyTypes.Remove(myType);
}
}
nyDbContext.SaveChanges();
}
}
至少目前,使用分离实体执行删除时异常似乎是不可避免的。您要么必须使用 try / catch
并处理异常,要么查询数据库以查找匹配的 ID,并且只删除匹配项 1.
异常处理示例
using (myContext)
{
foreach (long iterator in paramIeId)
{
nyDbContext.Remove(new MyType() { ID = iterator });
}
try
{
nyDbContext.SaveChanges()
}
catch(DbUpdateConcurrencyException ex)
{
//if you want special handling for double delete
}
}
样本查询然后删除
请注意,我在循环之前查询了整个类型列表,以避免对每种类型进行单独查询。
using (myContext)
{
var existingMyTypes = nyDbContext.MyTypes.Where(x => paramIeId.Contains(x.ID));
foreach (MyType existing in existingMyTypes)
{
nyDbContext.Remove(existing);
}
nyDbContext.SaveChanges();
}
1 注意:查询然后删除选项会打开一个可能的竞争条件,这可能会触发您尝试的 OptimisticConcurrencyException
- 即,如果另一个进程 /线程/程序删除您自己进程的读取和删除之间的行。完全处理这种可能性的唯一方法是在 try / catch
.