2011-07-03 16 views
5

He estado recibiendo informes de error de frecuencia razonable de mis usuarios, una típica es:conflicto LINQ - No encontró fila o cambiado

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) 

(que puedo dar más detalles si es necesario). El único código LINQ directa en esa función LoadArticle() es:

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

Puede haber otras funciones en LoadArticle que hacen referencia a los métodos que se ejecutan LINQ, pero estoy adivinando el StackTrace saldría de manera diferente, por lo que el código anterior es la causa .

¿Alguna idea de qué podría causar esto? Un conflicto de datos? ¿Cómo se resuelve este tipo de error usualmente?

¿Alguna idea de qué podría causar esto?

+0

actualizaciones simultáneas a la misma fila podrían desencadenar este. ¿Hay algún riesgo de eso? – bzlm

+0

@Bzlm, supongo que sí, el campo 'LastViewed' podría sufrir de eso, no he construido nada para manejar esto en el sitio. Aumenté la tasa de indexación de Google de mi sitio, así que este tipo de cosas es más probable, supongo. –

+0

y también el 'ArticlesCommon.Markdown (q.MarkupBody)' va a ser bastante lento, probablemente sea el culpable, el que se ejecuta cuando alguien está tratando de verlo, y las ideas de cómo resolverlo? –

Respuesta

6

He encontrado que los mecanismos de verificación de actualizaciones en L2S son una carga y no son útiles. Si necesita la protección de concurrencia, entonces probablemente debería dejarlos. Pero en mi caso, prescindir de los controles y dejar que el último en mantener sus ediciones fuera más que suficiente para mí. Con ese fin, deshabilité todas las comprobaciones de actualización para todas mis columnas, aunque es posible que tenga una razón para ser más exigente. Para ello, utilice la propiedad de UpdateCheckColumnAttribute la hora de definir sus propiedades:

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

Dicho esto, no creo que haya ninguna instalación en SQLMetal/dbml a hacer esto para usted, por lo que tendría generar las clases de entidad usted mismo (no es una mala idea de todos modos, muy poderosa).

+2

Creo que el problema es que Linq To Sql verifica sus columnas en la actualización y, a veces, las columnas en SQL Server pueden modificarse en su archivo .dbml. Aquí hay una respuesta alternativa que encontré útil: http://stackoverflow.com/questions/4104797/row-not-found-or-changed-linq-c-sharp-error-on-simple-statement-help-please – JoshVarty

0

Actualizar y eliminar solo funciona de la caja si ha agregado las tablas al archivo dbml. Si ha codificado manualmente sus entidades, tendrá que manejar manualmente la actualización y eliminar

2

Tuve el mismo error, en mi caso un desencadenante en la base de datos cambió la fila que estaba tratando de actualizar. Mi DbContext no tenía el cambio que hizo el disparador. La solución que encontré fue a llamar al método .Refresh() en el DbContext:

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

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