System.Data.Linq.ChangeConflictException:行未find或更改
我想使用LINQ(无LINQDataSource)删除选定的gridview行。
当select被改变时,detailview绑定也被改变。 我可以添加一个新的条目到数据库中,但是当我将这个代码添加到updatePanel中的一个删除button时,我得到一个exception:
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()
我有这个问题已经有一个星期了,不pipe我做了什么,它仍然存在,logging也不会被删除。
有什么想法做什么?
好的 – 它看起来好像(至less在我的情况下)答案是在DBML文件中将所有非主键列的UpdateCheck属性设置为从不 。 这样做立即解决了“行未find或改变”的问题。
考虑到微软正在将Linq-To-Sql转换为entity framework的传闻,人们不禁要问,这些错误是否会得到解决?
你得到这个错误很可能是因为你的一个字段在Linq To SQLdevise器和实际的数据库中有不同的东西。
就我而言,这是因为其中一个字段在数据库中是可空的,而在devise器中是不可空的,使得devise者可以空着,也立即解决了这个问题。
我遇到了同样的问题,并且遇到了这个博客 , 这个博客基本上说Linq-To-Sql在乐观并发中遇到了一个问题:
- 使用高精度的date时间字段。 解决方法是将UpdateCheck设置为从不为该列的DBML文件
- 被设置为不可见的GridView列正在访问数据对象的属性(这第二个原因是没有意义的,但似乎在这个博客上的所有愤怒)。
我还没有尝试过这些解决scheme,但是一旦有了,我会回到这里。
问题也可能只是表的DBML定义与数据库定义的状态不一致。 我刚刚删除了DBML模型,并从数据库中再次插入它,它工作。
希望这有助于某人。
我解决了这个问题,确保在更新之前立即刷新对象。 我用KeepChanges选项做这个。
db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, employee);
似乎也为我的情况工作。 我正在build立一个内存,从来没有提交过的行,有几个外键关系到其他表中的行。 InsertOnSubmit似乎工作,但随后DeleteOnSubmit给我那行未发现错误。 我没有填充我提交的行中的每一个字段,所以我不知道是否有什么关系,但标记所有主表的非主键列消除了错误信息。
还有一个想法:我认为将列的UpdateCheck策略标记为“从不”意味着它不被用作乐观协调检查的基础。 这意味着两个用户可以在任何这样的列上用不同的数据写一个给定的行,并且不会检测到冲突…意味着提交该行的最后一个用户将覆盖先前用户提交的值。 我从各种在线阅读中收集到一个解决scheme,就是在提交之前立即使用刷新方法来同步任何更改。 当然,在行上没有严格的locking,并不能保证该行在刷新和提交之间不会被改变,但是在涉及大型数据库的大多数情况下,这是很less见的。
更新:在进一步的审查,我想我已经发现了一个可能会影响其他人的情况,所以我想我会分享它,以防万一。 事实certificate,我一直使用SQL LINQ的问题至less有一部分与触发器有关。 看来,如果你使用SQL LINQ提交一行,而你的DBA有触发器,这些触发器被devise为将信息写入该行的某些列,那么SQL LINQ模型将默认为“始终”,确定该行自上次写入以来已经发生了变化。 我提交了部分填充的行,而我们的DBA的触发器正在填充一些列,所以当我试图进一步修改代码中的行时,它会根据触发器填充的列感知到更改冲突。 我正在调查现在处理这个最好的方法,但改变这些触发填充字段使用UpdateCheck政策的“当改变”或“从不”为我工作。 希望能帮助到你。
这仅仅是列定义不匹配的情况。 只需从.dbml
删除表并重新添加。 确保为具有自动生成数据的列(例如主键或date时间列)更改auto generate value property = true
。
更新行时,我有类似的changeconflictexception /“行未find或更改”。 通过在dbml中重新添加tabbles来解决它。
我遇到的问题是我在.net框架中有一个DateTimetypes,但是我们的数据库字段是DateTime2types,这是更高精度的数据types。 所以当我们提交更改时,对象的数据字段与数据库的距离只有几个纳秒,会导致并发错误。 当我们迁移到一个更新的MSSQL版本时,发生这种情况,它将我们的DateTime字段转换为DateTime2。
所以在我们的代码中,我们有:
Obj.DateUpdated = DateTime.Now()
我们将其更改为:
Obj.DateUpdated = DateTime.Parse(DateTime.Now.ToString())
因此,如果在进行升级或迁移后出现此错误,请检查您的数据types,特别是date字段。
确保没有列在相关表中包含null
值(即要更新的表)。
我能够通过在updatepanel回发期间在gridview和datasource上执行databind()来解决这个问题。
protected void UpdatePanel1_Load(object sender, EventArgs e) { GridView1.DataBind(); LinqDataSource1.DataBind(); }
每次我的select索引改变时,我刷新updatepanel,并能够解决冲突。
希望这可以帮助。
下:
QuestionModule o = query.First();
你必须添加下面的命令:
db.QuestionModule.Attach(o);
另外 – 如果您正在调用linqdatasource的select方法并手动设置e.result,请确保包含任何外键值。
没有别的工作对我来说,但这个。
我只是想为任何可能有此问题的人添加我的场景。
我们对我们的Linq to SQL dbml使用一个自定义的T4。 我们基本上只是修改了原来的get / setstring属性来自动修剪和设置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列以外的所有列上将并发检查设置为从不。 这对我们有效。
我有一个类似的问题,虽然删除和重新添加DBML表/类帮助一些用户,对我来说有点不同,因为我使用客户端上的分离实体和ListView的WCF。
如果我使用.Attach(实体)失败 – “行未find或改变”但是当使用.Attach(实体,原始)它每次工作
public void DeleteTask(Task task) { TwoDooDataContext db = new TwoDooDataContext(); db.Tasks.Attach(task,GetTaskByID(task.ID)); db.Tasks.DeleteOnSubmit(task); db.SubmitChanges(); }
对我来说,这是一个枚举列(映射到一个varchar)造成的问题,所以我不得不通过更新检查。
我解决这个问题的方法是:首先我更新数据库,然后将网格的新值设置为
e.Keys["ColumnOne"] ="new value" e.Keys["ColumnTwo"] ="new value"
所有这些都是在GridView_RowUpdating
事件下完成的。
正如@ dherrin79指出的,这可能是由于数据库和代码之间的精度差异造成的。 对于我来说,问题是数据库列应该是十进制(10,2),但它已被创build为十进制(18,0)。 这是一个货币领域,所以也许我应该使用钱列types。
所以,我节省了一美元的金额,如3.14美元,但小数点被剥离。 这导致数据库值被更改,并且不匹配C#中的值。
希望这可以帮助。