LINQ冲突 - 未找到或更改行

时间:2011-07-03 21:15:24

标签: c# asp.net linq conflict

我从用户那里得到了相当频繁的错误报告,典型的一个是:

Error Message: Row not found or changed.
Stack Trace:
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
at Controls_Article_ArticleViewer.LoadArticle() 
at ViewTutorial.Page_Load(Object sender, EventArgs e) 
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) 
at System.Web.UI.Control.LoadRecursive() 
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

(如果需要,我可以提供更多细节)。该函数LoadArticle()中唯一直接的LINQ代码是:

    using (MainContext db = new MainContext())
    {
        var q = (
                    from A in db.tblArticles
                    where A.ID == this.ArticleID && A.IsDeleted == false
                    select A
                ).SingleOrDefault();
        if (q == null)
        {
            Server.Transfer("~/404.aspx");
            Context.Response.End();
        }
        else
        {
            // Cache expired for HTML generation
            if (q.HTMLLastGenerated.AddSeconds(Settings.ArticleRegenHTMLCacheSecs) < DateTime.Now)
            {
                q.Body = ArticlesCommon.Markdown(q.MarkupBody);
                q.HTMLLastGenerated = DateTime.Now;
            }

            q.Views++;
            q.LastView = DateTime.Now;
            db.SubmitChanges();

            // Set passbakcs
            this.AuthorID = q.AuthorID;
            this.Anchor = q.Anchor;
            this.SectionID = q.SectionID;
            this.Views = q.Views;
            this.DatePublished = q.Date;
            ArticleAnchor = q.Anchor;
            ArticleAuthorID = q.AuthorID;

            // Get the latest edit
            ArticleEdit LatestEdit = ArticleEditCommon.GetLatestEdit(this.ArticleID);
            // An edit exists!
            if (LatestEdit.ID != 0)
            {
                this.Description = LatestEdit.Description;
                this.ArticleTitle = LatestEdit.Title;
                ArticleBody.Text = LatestEdit.Body;
                ArticleH1.Text = ArticleTitle;
            }
            // No edits
            else
            {
                this.Description = q.Description;
                this.ArticleTitle = q.Title;
                ArticleBody.Text = q.Body;
                ArticleH1.Text = ArticleTitle;
            }

            // Get toal comments
            TotalComments = (from C in db.tblComments where C.IsDeleted == false && C.Anchor == ArticleAnchor select new { C.ID }).Count();

            // Get author details
            var qq = (from A in db.tblForumAuthors where A.Author_ID == ArticleAuthorID select new { A.Username }).Single();
            AuthorUsername = qq.Username;
        }
    }

LoadArticle中可能有其他函数引用运行LINQ的方法,但我猜测堆栈跟踪的结果会有所不同,所以上面的代码就是原因。

关于导致这种情况的任何想法?数据冲突?这种错误通常是如何解决的?

任何想法会导致什么?

3 个答案:

答案 0 :(得分:6)

我发现L2S中的更新检查机制是一种负担并且无益。如果你需要并发保护,那么你应该把它们留进去。但在我的情况下,免除支票并让最后一个保留他的编辑对我来说已经绰绰有余了。为此,我禁用了所有列的所有更新检查,尽管您可能有理由更具辨别力。为此,请在定义属性时使用UpdateCheck ColumnAttribute属性:

[Column(Storage="lastView", Name="LastView", 
 DbType="datetime", UpdateCheck=UpdateCheck.Never)]
public DateTime LastView { ... }

话虽这么说,我不相信sqlmetal / dbml中有任何设施可以为你做这个,所以你必须自己生成实体类(不管怎样都不是一个坏主意 - 非常强大)。 / p>

答案 1 :(得分:2)

我遇到了同样的错误,在我的情况下,数据库上的触发器改变了我试图更新的行。我的DbContext没有触发所做的更改。 我找到的解决方案是在.Refresh()上调用DbContext方法:

var productToUpdate = _dbContext.Products.SingleOrDefault(p => p.ID == product.ProductID);
_dbContext.Refresh(RefreshMode.OverwriteCurrentValues, productToUpdate);

// do changes...
_dbContext.SubmitChanges();

答案 2 :(得分:0)

如果已将表添加到dbml文件,则仅更新和删除即可使用。如果您手动编码了实体,则必须手动处理更新和删除