我正在审核一些EF代码,我想知道为什么它似乎有效。
代码很简单。我们有一个表需要查询来确定其主键的正确字段。可能在查询运行和提交插入之间,某些其他进程已插入新记录,因此插入失败并发生主键冲突。 (这可以通过主键中的标识字段更好地处理,但这不是我现在可以做的重构。)为了解决这个问题,原始程序员使用了循环:
MyRec myRec = new MyRec
{
//.. set fields
};
bool isDone = false;
int retries = 0;
const int maxRetries = 8;
while (retries < maxRetries && !isDone)
{
myRecseqno = getSeqno();
try
{
myDbContext.myRecs.Add(myRec);
myDbContext.SaveChanges();
isDone = true;
}
catch
{
retries++;
}
}
我不喜欢的一件事是它捕获了每个异常,而不仅仅是主键违规。 (我不喜欢的另一件事是这个函数在四个不同的类中有四个相同的副本)。但这不是我的问题。假设我会解决这个问题。
困扰我的是myRec被多次添加到集合中,我不希望这样做。 DbContext是一个工作单元,这意味着如果在第一次传递时将记录添加到集合中,则在第二次循环中它再次添加时它仍然在集合中。
请记住,主键已更改,因此我认为该集合将包含两个记录,在第二个循环之后,第一个包含原始主键,第二个包含新主记录。
当您将同一个对象添加到集合中时,EF是否会使用对象标识来识别两次?
答案 0 :(得分:0)
可能会建议您执行查询并在事务中插入,这会产生锁定并阻止其他进程插入。存储过程可以提供最佳性能,或查看http://blogs.msdn.com/b/alexj/archive/2009/01/11/savechanges-false.aspx