当DB中有数据时,为什么“SingleOrDefault”在第二次执行时返回null?

时间:2014-03-11 07:31:23

标签: asp.net linq entity-framework

我正在使用EF处理ASP.NET MVC 4.5站点。我有代码检查数据库中的记录是否存在,如果不存在则创建新记录。由于我的代码中的一个问题,我后来修复了,我在几分之一秒内调用了这个代码两次。结果是创建了重复记录。这是我的代码:

    Word wordToUpdate = context.Words.SingleOrDefault(w => w.Label == word);
    if (wordToUpdate == null) // word doesn't exist yet so make a new one
    {
      Word w = new Word() { 
      // add new word stuff here   
      };
      context.Words.Add(w);
    }
    else 
    {
      // word already exists so just add stuff to existing entry
      wordToUpdate.AnnotationGroups.Add(ag);  
    }
    context.SaveChanges();

如果数据库中尚不存在该单词,则会添加两次。以下是重复记录的时间戳:

CreatedOn
2014-03-11 06:52:35.743
2014-03-11 06:52:50.637

我在观看数据库记录时逐步完成了代码,并在第一次执行时添加了新记录,因此:

  1. 当数据库中有匹配的记录时,为什么context.Words.SingleOrDefault()在第二次执行时返回null?
  2. 此表中不应存在重复记录。如何改进我的代码以确保它不可能发生?
  3. 修改

    让我在上面的代码片段的开头用一个断点调试时添加一些我观察到的细节:

    1. 第一次调用它时,一切都按预期工作 - 因为它是一个新单词wordToUpdate为空并且添加了一个新单词。
    2. 我停止了context.SaveChanges()处的代码并检查了数据库 - 新行显示添加了新单词
    3. 下一个调用(这是来自Ajax.ActionLink链接的AJAX调用)使用相同的单词激活
    4. wordToUpdate返回null,即使DB已经包含该单词,因此添加了该单词的重复条目(我没有使用该单词作为主键,我宁愿在代码中处理它而不是尝试从DB抛出的句柄错误
    5. 再次调用context.SaveChanges时,另一行将添加到数据库
    6. 所以我的问题是,因为这个调用来自同一个客户端,实际执行的代码是同步的吗?它在调试中逐步执行代码的方式似乎暗示了这一点,但这是我对ASP.NET的了解有点模糊的地方。

1 个答案:

答案 0 :(得分:1)

也许您的问题与您使用的断言有关:w => w.Label == word

如果要比较对象,即使它们可能具有相同的内容,==只是比较它们是否具有相同的内存地址,这是默认实现。您应该在Word类中重写Equals,以便行为比较键值或类似值。