Linq行未找到或更改

时间:2012-01-13 13:42:00

标签: c# asp.net linq linq-to-sql 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) 

这似乎是随机发生的。我通过电子邮件发送了这些错误,并且报告的URL似乎总是对我有用,并且应该对其他人也有效。

我可以通过以下方式解决此错误:

  • 转到我的dbml布局
  • 选择表格中的每个字段会导致冲突
  • 右键单击并将属性Update Check设置为Never

这似乎可以防止抛出这些类型的错误。

但是,每当我有机会进入dmbl,添加新表等时,记住继续这样做是很费力的。有没有更好的方法来解决这个问题?我每天可能会得到50-100个这对我的访客来说很糟糕。

9 个答案:

答案 0 :(得分:50)

我有同样的问题,并通过比较dbml和db结构来解决它。一个属性未设置为可空,这导致了问题。

请检查您的dbml和可空属性。

答案 1 :(得分:28)

每次我看到这个错误,都意味着在我加载记录/对象/什么以及我试图保存它的时间之间数据库中发生了什么变化。没错,那是因为我的工作单位太大了。

我不知道您的应用程序的确切性质,但我假设您正在创建数据上下文,加载记录或记录列表,对其执行某些操作,咀嚼一些时间和处理器周期,以及然后在最后尝试将修改后的数据保存回数据库。甚至可能加载一个记录/对象的实例并将其存储在类变量中一段时间​​,然后在页面加载或线程的末尾或任何试图保存更改的内容。问题是因为LINQ存储了它的副本,即它想要更新的副本。如果基础数据在此期间发生变化,那就太疯狂了。

问问自己,如果在对象的整个生命周期内对数据进行锁定事务,该怎么办?说你加载的任何东西都可以修改,在此期间没有其他人可以接触它。基本上这就是这里的假设。当然,LINQ对它更加乐观,如果你可能永远不会更新数据,那么锁定行或表是没有意义的,但你会想到这些问题。问问自己,如果要对对象进行严格的事务锁定会导致什么会破坏或显着减慢,这可能会指向违规代码。

我的解决方案是尽可能减少我的工作单元。不要加载对象并将其用作工作副本并将其存储回数据库,所有这些都在一个上下文中。相反,加载对象并在一个步骤中提取所需的信息,然后找出需要应用的更改,然后加载/更新/保存对象。当然它会导致更多往返数据库,但可以更好地保证您正在使用最新的数据副本。它仍将是“最后赢,赢”,这意味着如果有人在您处理数据时进行了更新,则可能会丢失,但除非您使用事务锁定记录,否则这总是存在风险。但是,如果其他人正在修改同一行中不相关的字段,那么它确实会为您带来灵活性,您可以同时对这些数据进行操作。

答案 2 :(得分:2)

GetTable()。附加(newEntity,originalEntity);

如果您没有使用版本字段进行更新,上面的方法会参数化新的详细信息和旧的详细信息实体,如果此时更改了原始实体,您仍会得到相同的错误,这取决于您确保。这就像一个魅力,我尝试过。

答案 3 :(得分:2)

如果数据库触发器更改了您正在更新的行中的任何列,也会发生这种情况 - 即使您没有更新该特定列。

您必须仔细检查您工作单元中受影响的任何表都没有触发器。如果您使用的是更新触发器,那么您可能希望确保更新的列是 NeverCheck

答案 4 :(得分:1)

有时它非常简单......确保桌子上没有锁。就我而言,在我调试时,SQL Server Management Studio UI保存了我不知道(不记得)的锁。卸载它清除了那些锁,事情又重新开始了。

答案 5 :(得分:1)

使用SQL事件探查器我跟踪了我的服务器的SQL事务,并意识到SubmitChanges() UPDATE语句在WHERE子句中包含错误值 。这是因为我有一个看起来像这样的属性:

class Position{
...
    [Column]
    public int Pieces{
        get{
            this.pieces = this.Transformers.Count;

            return this.pieces;
        }
        set{ this.pieces = value; }
    }
...
}

由于Transformers是一个List<Transformers>元素,表示与另一个Transformers表的一对多关系列表,因此我需要手动填写每个Transformer的列表包含我的Position对象的外键。如果由于某种原因,我不这样做,那么我将得到提到的错误,因为Pieces属性偏离原始值。

因此,SubmitChanges()上的SQL语句将搜索条目WHERE Pieces = somevalue,但条目中Pieces的实际值为anothervalue。所以基本上LINQ会认为,你同时在db中改变了一些东西,因为db不会给这个请求返回任何值。

如上所述,一种解决方案是:

    [Column(UpdateCheck=UpdateCheck.Never)]
    public int Pieces
    {
        get {
            this.pieces= this.Transformers.Count;

            return this.pieces; 
        }
        set { this.pieces= value; }
    }

当然,通过设置像

这样的简单getter函数,也可以轻松解决这个问题
getPieces(){
    return this.Transformers.Count();
}

和“无偏见”的财产

class Position{
...
    [Column]
    public int Pieces{
        get{ return this.pieces; }
        set{ this.pieces = value; }
    }
...
}

我希望这可以对某人有所帮助。我也发布了这个帖子,因为如果以前有其他人的话,它会为我节省数小时的生命。

答案 6 :(得分:0)

我在Windows Phone 8上遇到了这个错误。我花了一段时间来弄清楚问题是什么。基本上是这样的:

我有一个叫做TrackingInformation的课程。 1.从服务器我获取了它的更新版本。 2.我的TileService使用它的信息和(!!)更新了1个属性更新了辅助磁贴,并将其保存到手机上的本地数据库中。 3.我试图再次保存对象的第一个实例,在这里我得到错误&#34;未找到或更改行#34;。

对我来说,我只需要删除第三部分,它工作正常(我已经保存了更新版本)。但由于一处房产发生了变化,它引发了例外......

我不能等到EF7进入Windows Phone,对WP8上的当前EF感到非常头疼。

答案 7 :(得分:0)

在我的案例中将linq更新为sql架构的设计器解决问题

答案 8 :(得分:0)

我遇到了同样的问题。问题发生在更新行的地方。

例如,我有一个带有列的表:

id,firstname,lastname,age

我想使用dbml更新年龄。在探查器中,我看到了 更新age=@newage,其中id=@idfirstname=@firstnamelastame=@lastname

但是在读取行和更新之间,其他一些过程更改了名字或姓氏值。 UPDATE失败是因为WHERE子句对于其中一列具有不同的值,并且更新将@@rowcount==0返回到dbml,这将使您得到的错误得到解决。