LINQ to SQL - 使用OnPropertyChanged更新时“未找到或更改行”

时间:2012-07-28 16:33:16

标签: c# linq linq-to-sql override plinqo

以下代码中的Save方法失败,并显示错误“Row not found or changed”。

Question question = questionService.getQuestionById(id); 
// returning Context.Question.Where(q => q.id == id).SingleOrDefault()

question.Text = "some text";

questionService.Save(question); 
// Context.SubmitChanges();

问题是使用CodeSmith和PLINQO模板生成的DTO。但是,只有在对OnPropertyChanged事件实现自定义覆盖以在创建或修改记录时自动插入后,才会出现“未找到或未更改行”错误。我分析了生成的查询,当执行getQuestionById方法时,它正在执行正常的select语句。但是,如果修改日期返回为“2012-07-28 12:15:00.900”,则当我尝试保存记录时,更新失败,因为它正在添加Modified ='2012-07-28 12:15: 00.903'到更新语句,这与数据库中存在的几毫秒不同。所以我知道这与添加到生成的Question对象的以下代码有关:

protected override void OnPropertyChanged(string property)
{
    this.UpdateProperties(property);
    base.OnPropertyChanged(property);
}

public static void UpdateProperties(this object updatedObject, string property)
{
    if (property == created || property = modified) return;
    // prevents an infinite loop 

    Update(updateObject);
    // sets updatedObject.Created and updateObject.Modified fields
}

我发现一些帖子建议将UpdateMode设置为从不在dbml中使用精度高于秒的字段。我可以使用它作为最后的手段,但我已经将相同的代码添加到具有相同数据类型的其他表一段时间没有任何问题,并且想要理解为什么它只发生在这一个表中。这似乎也有点随机失败,我没有具体的步骤来重现它,但是当我没有调试时它似乎更频繁地发生。

1 个答案:

答案 0 :(得分:0)

我的猜测是你正在使用数据库中的Modified(和/或Created)列来检查并发性。您也在自己更新此列。这种混合不正确。

更好的方法是使用时间戳作为并发检查列。此列将由SQL服务器设置(假设这是您正在使用的),并且不是日期时间,而是一些内部唯一数据库生成的值。

一些谷歌搜索给了我this文章,我认为这将很好地解释如何设置时间戳列的基础知识。