2009-04-30 75 views
51

我想删除使用LINQ(无 的LinqDataSource)选定gridview的行。System.Data.Linq.ChangeConflictException:未找到行或更改

当选择改变时,在DetailsView结合被改变 也。我可以在新的条目添加到数据库中,但是当我加入这个 代码的UpdatePanel内删除按钮,我得到了一个例外:

try 
{   
    var query = from i in db.QuestionModules 
       where i.QuestionModuleID == QuestionModuleID 
       select i; 

    QuestionModule o = query.First(); 
    db.QuestionModules.DeleteOnSubmit(o); 
    db.SubmitChanges(); 
} 

这是例外,我得到:

System.Data.Linq.ChangeConflictException: Row not found or changed. at 
System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode 
failureMode) at 
System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges() 

我有这个问题已经有一个星期了,不管我做什么,它仍然是 ,并且记录不会被删除。

关于该怎么做的任何想法?

回答

15

我有同样的问题,和整个this blog,基本上说的LINQ到SQL得到了一个问题,这也正是乐观并发来了:用于

  1. 高精度日期时间字段。解决的办法是设置UpdateCheck的永不该列的DBML文件
  2. 被设置为不可见的数据对象的访问属性(这第二个原因是没有意义的,但它似乎是所有上风靡一时的GridView列博客)。

我还没有尝试过这些解决方案,但是一旦有了,我会回到这里。

+0

好的 - 我刚刚尝试将所有Date列的UpdateCheck设置为Never ...没有快乐,我仍然得到相同的结果。 – Mark 2009-07-06 13:23:21

+0

我有一些日期时间字段更新相同的问题:更改UpdateCheck值解决了问题。 – 2011-06-05 10:18:44

+2

+1我有这个问题,SQL数据库上有一个`float`字段,我已经将它映射到C#中的`float`(single)类型。当我将类型改为“双”时,问题就消失了。但是你的这个答案引发了我的关注 - 所以谢谢! – 2011-06-06 15:03:55

66

确定 - 它看起来好像(在我的情况下,至少)的答案是所有非主键列的UpdateCheck的属性设置为决不在DBML文件。这样做立即解决了“找不到或更改行”的问题。

鉴于传闻,微软是蛾泥包支持实体框架的LINQ到SQL中,无论是这些类型的错误都将被固定人们不禁要问?

+1

这可能有效,但天哪,这是可取的吗?不适合我! – 2012-11-01 18:05:38

+0

+1,因为它的工作。任何人都可以流下。有关这方面的影响的一些信息。博客文章或以其他方式将是伟大的。谢谢。 – Kieran 2012-11-22 03:51:20

0

下:

QuestionModule o = query.First(); 

你必须添加下面的命令:

db.QuestionModule.Attach(o); 
1

确保没有列包含相关表null值(即表进行更新)。

0

我能够回发的UpdatePanel期间执行数据绑定()在GridView和数据源来解决这个问题。

protected void UpdatePanel1_Load(object sender, EventArgs e) 
    { 
     GridView1.DataBind(); 
     LinqDataSource1.DataBind(); 
    } 

我每次刷新updatepanel时,我的选择索引发生变化,它能够解决冲突。

希望这会有所帮助。

6

似乎也适用于我的情况。我在内存中建立一个从未提交过的行,这个行与其他表中的行有几个外键关系。InsertOnSubmit似乎工作,但随后DeleteOnSubmit给我那行未发现错误。我没有填充我提交的行中的每个字段,所以我不知道这与它有什么关系,但标记了所有主表的非主键列都消除了错误消息。

一个进一步的思考:我是否可以认为标志着一个列的UpdateCheck的政策为“从不”意味着不作为乐观并发性检查的基础。这意味着两个用户可以在任何这样的列中使用不同的数据在给定的行上进行编写,并且不会检测到冲突......这意味着提交行的最后一个用户将覆盖先前用户提交的值。我从各种在线阅读中收集到一个解决方案,即在提交之前立即使用刷新方法来同步所有更改。当然,对行不加锁定,不保证该行在刷新和提交之间不会改变,但在涉及大型数据库的大多数情况下,这种情况很少发生。

更新:在进一步审查,我想我已经发现了,所以我想我会为了以防万一分享可能会影响其他人的情况。事实证明,使用SQL LINQ至少有一部分问题与触发器有关。看起来,如果您使用SQL LINQ提交一行,并且您的DBA具有旨在将信息写入该行中某些列的触发器,那么SQL LINQ模型将默认为“始终”,以确定该行自上次写入以来已更改。我提交了部分填充的行,而我们的DBA的触发器填充了一些列,因此当我试图进一步修改代码中的行时,它会根据触发器填充的列感知到更改冲突。我现在正在调查处理这个问题的最好方法,但将这些触发器填充的字段更改为使用“更改时间”或“从不”的UpdateCheck策略为我工作。希望能帮助到你。

2

我在更新行时发生了类似的changeconflictexception /“Row not found or changed”行。 通过在dbml中重新添加tabbles来解决它。

12

问题可能还仅仅是表的DBML定义不与数据库定义的状态一致。我刚刚删除了DBML模型并将其从数据库中再次插入,并且它工作正常。

希望这有助于某人。

46

你很可能得到这个错误,因为你的领域之一,在LINQ的不同的东西to SQL设计,并在实际的数据库。

在我的情况,这是因为该领域之一是在数据库中可空,并在设计师不能为空,使得它在和亟待解决的问题设计为空。

0

另外 - 如果您要调用linqdatasource的选择方法并手动设置e.result,请确保您也包含任何外键值。

没有别的为我工作,但这。

0

我固定它的方式是:首先,我更新数据库,然后我设置为网格的新值

e.Keys["ColumnOne"] ="new value" 
e.Keys["ColumnTwo"] ="new value" 

这一切的GridView_RowUpdating事件下完成的。

0

我只是想为任何可能有此问题的人添加我的场景。

我们对我们的Linq to SQL dbml使用自定义T4。我们基本上只是修改了原来的get/set字符串属性来自动修剪和设置null。

 get { return _OfficiantNameMiddle.GetValueOrNull(); } 
     set 
     { 
      value = value.GetValueOrNull(); 
      if (_OfficiantNameMiddle != value) 
      { 
       _IsDirty = true; 
       OnOfficiantNameMiddleChanging(value); 
       SendPropertyChanging("OfficiantNameMiddle"); 
       _OfficiantNameMiddle = value; 
       SendPropertyChanged("OfficiantNameMiddle"); 
       OnOfficiantNameMiddleChanged(); 
      } 
     } 

在我们的数据库中遗留数据有一些前/后间隔等等这些列的任何并发检查失败,导致在比赛(这是比较对非修剪数据库值的修整值)。对SQL进行概要分析非常简单,只需在并发检查期间开始返回一行,即可获取SQL并开始注释WHERE子句中的项目。

幸运的是,我们的表中有一个LastUpdatedOn字段,通过OnValidate(System.Data.Linq.ChangeAction)自动设置。

partial void OnValidate(System.Data.Linq.ChangeAction action) 
    { 
     if (action == System.Data.Linq.ChangeAction.Insert) 
     { 
      CreatedBy = CurrentUserID; 
      CreatedOn = DateTime.Now; 
      LastUpdatedBy = CreatedBy; 
      LastUpdatedOn = CreatedOn; 
     } 
     else if (action == System.Data.Linq.ChangeAction.Update) 
     { 
      LastUpdatedBy = CurrentUserID; 
      LastUpdatedOn = DateTime.Now; 
     } 
    } 

为了绕过这个问题,我们只需设置并发检查,不要在所有列,除了主键列和LastUpdatedOn列。这对我们有效。

0

我有一个类似的问题,虽然删除和重新添加DBML表/类帮助一些用户,对我来说有点不同,因为我在客户端使用WCF与分离的实体和ListView。

如果我用了.Attach(实体)失败 - “未找到行或更改” 但在使用时.Attach(实体,原件)它屡试不爽

public void DeleteTask(Task task) 
    { 
     TwoDooDataContext db = new TwoDooDataContext(); 
     db.Tasks.Attach(task,GetTaskByID(task.ID)); 
     db.Tasks.DeleteOnSubmit(task); 
     db.SubmitChanges(); 
    } 
0

对我来说是一个引起问题的enum列(映射到varchar),所以我不得不通过更新检查。

8

我解决了这个问题,确保在更新之前立即刷新对象。我使用KeepChanges选项执行此操作。

db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, employee); 
2

我的问题是,我在.NET Framework中一个DateTime类型,但我们的数据库字段是DATETIME2类型,这是更高的精度数据类型。因此,当我们提交更改时,对象的数据字段与数据库的距离仅为几纳秒,这会导致并发错误。当我们迁移到一个更新的MSSQL版本并将DateTime字段转换为DateTime2时,就发生了这种情况。

在我们的代码,我们不得不

所以:

Obj.DateUpdated = DateTime.Now() 

我们把它改为:

Obj.DateUpdated = DateTime.Parse(DateTime.Now.ToString()) 

因此,检查你的数据类型,尤其是你的日期字段,如果你做一个升级后出现此错误和/或迁移。

3

这只是一个不匹配列定义的例子。只需从.dbml中删除表格并重新添加即可。确保为具有自动生成数据的列(如主键或日期时间列)更改auto generate value property = true

0

正如@ dherrin79指出的,这可能是由于数据库和代码之间的精度差异造成的。对我来说,问题是数据库列应该是十进制(10,2),但是它已经被创建为十进制(18,0)。这是为了金钱领域,所以也许我应该使用钱列类型。

所以,我节省了一美元的金额,如3.14美元,但小数点被剥离。这导致数据库值被更改并且不匹配C#中的值。

希望这会有所帮助。

相关问题