2011-07-03 14 views
5

tôi đã nhận được báo cáo lỗi một cách hợp lý thường xuyên từ người dùng của tôi, một điển hình là:LINQ xung đột - hàng không tìm thấy hoặc thay đổi

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) 

(tôi có thể cung cấp thêm chi tiết cụ thể nếu cần thiết). Các chỉ LINQ mã trực tiếp trong hàm LoadArticle() là:

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

Có thể có các chức năng khác trong LoadArticle mà tham khảo phương pháp mà chạy LINQ, nhưng tôi đoán stacktrace sẽ đi ra khác nhau, do các mã trên là nguyên nhân .

Bất kỳ ý tưởng nào về điều gì sẽ gây ra điều này? Xung đột dữ liệu? Loại lỗi này thường được giải quyết như thế nào?

Bất kỳ ý tưởng nào sẽ gây ra điều này?

+0

cập nhật đồng thời để cùng hàng có thể kích hoạt này. Có nguy cơ gì không? – bzlm

+0

@Bzlm, tôi cho là có, trường 'LastViewed' có thể bị ảnh hưởng bởi điều đó, tôi chưa tạo bất cứ thứ gì để xử lý điều này vào trang web. Tôi đã tăng tỷ lệ lập chỉ mục của Googles trên trang web của mình để loại điều này có nhiều khả năng tôi đoán? –

+0

và 'ArticlesCommon.Markdown (q.MarkupBody)' sẽ khá chậm, đó có thể là thủ phạm, chạy khi ai đó đang cố gắng xem nó, và ý tưởng làm thế nào để giải quyết vấn đề này? –

Trả lời

6

Tôi đã tìm thấy cơ chế kiểm tra cập nhật trong L2S ​​là một gánh nặng và vô ích. Nếu bạn cần sự bảo vệ đồng thời, thì có lẽ bạn nên để chúng lại. Nhưng trong trường hợp của tôi, việc phân phát các kiểm tra và cho phép người cuối cùng giữ các chỉnh sửa của mình là quá đủ cho tôi. Để kết thúc, tôi vô hiệu hóa tất cả các kiểm tra cập nhật cho tất cả các cột của tôi, mặc dù bạn có thể có một lý do để phân biệt đối xử hơn. Để làm như vậy, sử dụng tài sản của UpdateCheckColumnAttribute khi xác định tài sản của bạn:

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

Điều đó đang được nói, tôi không tin có bất kỳ cơ sở trong sqlmetal/dbml để làm điều này cho bạn, vì vậy bạn phải để tự tạo ra các lớp thực thể (không phải là một ý tưởng tồi - rất mạnh).

+2

Tôi nghĩ rằng vấn đề là LINQ Để Sql kiểm tra các cột của bạn trên cập nhật và đôi khi các cột trong SQL Server có thể được thay đổi trong tập tin .dbml của bạn. Dưới đây là một câu trả lời thay thế mà tôi thấy hữu ích: http://stackoverflow.com/questions/4104797/row-not-found-or-changed-linq-c-sharp-error-on-simple-statement-help-please – JoshVarty

0

Chỉ cập nhật và xóa các tác phẩm ra khỏi hộp nếu bạn đã thêm các bảng vào tệp dbml. Nếu bạn đã mã hóa các thực thể của mình, bạn sẽ phải xử lý cập nhật thủ công và xóa

2

Tôi đã gặp lỗi tương tự, trong trường hợp của tôi, trình kích hoạt trên cơ sở dữ liệu đã thay đổi hàng mà tôi đang cố cập nhật. My DbContext không có thay đổi kích hoạt. Giải pháp tôi thấy được để gọi phương thức .Refresh() trên DbContext:

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

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