2011-07-03 14 views
5

byłem coraz rozsądnie częste raporty o błędach z moich użytkowników, typowy jeden jest:LINQ konflikt - nie znaleziono rzędzie lub zmienione

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) 

(mogę podać więcej szczegółów w razie potrzeby). Jedyny bezpośredni kod LINQ w tej funkcji LoadArticle() jest:

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

Mogą być też inne funkcje w LoadArticle że referencyjne metody, które działają LINQ, ale jestem zgadywania StackTrace wyjdzie inaczej, więc powyższy kod jest przyczyną .

Jakieś pomysły, co by to spowodowało? Konflikt danych? Jak zwykle rozwiązuje się ten rodzaj błędu?

Jakieś pomysły, co by to spowodowało?

+0

jednoczesnych aktualizacje do tego samego wiersza może spowodować to. Czy istnieje jakiekolwiek ryzyko? – bzlm

+0

@Bzlm, Przypuszczam, że tak, pole 'LastViewed' może cierpieć z tego powodu, nie zbudowałem nic, aby obsłużyć to na stronie. Zwiększyłem wskaźnik indeksowania w Google dla mojej witryny, więc wydaje mi się, że takie rzeczy są bardziej prawdopodobne? –

+0

, a także "ArticleCommon.Markdown (q.MarkupBody)" będzie dość powolny, to prawdopodobnie sprawca, który działa, gdy ktoś próbuje go wyświetlić, i pomysły, jak rozwiązać ten problem? –

Odpowiedz

6

Znalazłem mechanizmy sprawdzania aktualizacji w L2S jako obciążenie i niepomocne. Jeśli potrzebujesz ochrony przed współbieżnością, prawdopodobnie powinieneś je zostawić. Ale w moim przypadku, rezygnacja z odpraw i wypuszczenie ostatniego z nich sprawia, że ​​jego edycje są dla mnie więcej niż wystarczające. W tym celu wyłączyłem wszystkie kontrole aktualizacji dla wszystkich moich kolumn, chociaż możesz mieć powód do większej dyskryminacji. Aby to zrobić, należy użyć właściwości ColumnAttributeUpdateCheck podczas definiowania właściwości:

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

Mając na uwadze powyższe, nie wierzę, istnieje jakikolwiek obiekt w SQLMetal/dbml to zrobić dla ciebie, więc musiałbyś do generowania klas jednostek samodzielnie (nie jest to zły pomysł - bardzo silny).

+2

Myślę, że problem polega na tym, że Linq To Sql sprawdza twoje kolumny przy aktualizacji i czasami kolumny w SQL Server mogą być zmienione w twoim pliku .dbml. Oto alternatywna odpowiedź, która okazała się pomocna: http://stackoverflow.com/questions/4104797/row-not-found-or-changed-linq-c-sharp-error-on-simple-statement-help-please – JoshVarty

0

Aktualizowanie i usuwanie działa po wyjęciu z pudełka tylko po dodaniu tabel do pliku dbml. Jeśli masz handcoded swoich podmiotów, będziesz musiał ręcznie obsługiwać aktualizację i usunąć

2

Miałem ten sam błąd, w moim przypadku wyzwalacz w bazie danych zmienił wiersz, który próbowałem zaktualizować. Mój DbContext nie zmienił ustawionego wyzwalacza. Rozwiązanie znalazłem wywołać metodę .Refresh() na DbContext:

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

// do changes... 
_dbContext.SubmitChanges(); 
Powiązane problemy