Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ conflict - Row not found or changed

I've been getting reasonably frequent error reports from my users, a typical one is:

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)

(I can give more specifics if needed). The only direct LINQ code in that function LoadArticle() is:

    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;
        }
    }

There may be other functions in LoadArticle that reference methods that run LINQ, but I am guessing the stacktrace would come out differently, so the code above is the cause.

Any ideas as to what would cause this? A data conflict? How is this sort of error resolved usually?

Any ideas what would cause this?

like image 376
Tom Gullen Avatar asked Jul 03 '11 21:07

Tom Gullen


2 Answers

I've found the update check mechanisms in L2S to be a burden and unhelpful. If you need the concurrency protection, then you should probably leave them in. But in my case, dispensing with checks and letting the last-one-in keep his edits was more than sufficient for me. To that end, I disabled all the update checks for all my columns, though you may have a reason to be more discriminating. To do so, use the UpdateCheck property of ColumnAttribute when defining your properties:

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

That being said, I don't believe there is any facility in sqlmetal/dbml to do this for you, so you'd have to generate the entity classes yourself (not a bad idea anyway -- very powerful).

like image 174
Kirk Woll Avatar answered Nov 09 '22 14:11

Kirk Woll


I had the same error, in my case a trigger on the database changed the row I was trying to update. My DbContext didn't had the change the trigger made. The solution I found was to call the .Refresh() method on the DbContext:

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

// do changes...
_dbContext.SubmitChanges();
like image 33
Erik de Wilde Avatar answered Nov 09 '22 13:11

Erik de Wilde