当上下文尚未保存时使用“任何”或“包含”

时间:2013-11-12 16:34:34

标签: linq entity-framework dbcontext

为什么没有触发异常? Linq的“Any()”没有考虑新的条目?

MyContext db = new MyContext();

foreach (string email in {"asdf@gmail.com", "asdf@gmail.com"})
{
   Person person = new Person();
   person.Email = email;

   if (db.Persons.Any(p => p.Email.Equals(email))
   {
       throw new Exception("Email already used!");
   }

   db.Persons.Add(person);
}

db.SaveChanges()

第二次迭代不应该触发异常吗?

以前的代码适用于该问题,但实际情况如下:
我收到了一个优秀的人,我迭代它将每行作为一个人添加到db.Persons,检查他们的电子邮件尚未在数据库中使用。问题是当工作表本身有重复的电子邮件时(两行有相同的电子邮件)

3 个答案:

答案 0 :(得分:1)

db.Persons的调用将始终触发数据库查询,但这些新人员尚未持久保存到数据库。

答案 1 :(得分:1)

是 - 仅根据数据源计算查询(按设计)。如果要查询内存中的项目,还可以查询Local商店:

if (db.Persons.Any(p => p.Email.Equals(email) || 
    db.Persons.Local.Any(p => p.Email.Equals(email)  )

但是 - 由于你控制了添加到商店的内容,检查代码中的重复内容是否有意义而不是EF?或者这只是一个人为的例子?

此外,为现有项目抛出异常似乎也是一个糟糕的设计 - 异常可能很昂贵,如果客户端不知道捕获它们(在这种情况下比较异常的消息),它们可以导致整个程序意外终止。

答案 2 :(得分:0)

我想如果你看看调试中的数据,你会发现新人在第二次迭代中不存在。如果你再次设置MyContext db = new MyContext(),那就是,但你不会在真实情况下这样做。

您需要解决的实际用例是什么?这个例子似乎不会在真实情况下发生。

如果您正在与db进行比较,那么您的代码应该可行。如果您需要防止输入重复,它应该发生在其他地方 - 在客户端上或在开始将其写入数据库之前检查C#集合。