Linq-to-Sql SubmitChanges没有更新字段……为什么?

我昨天晚上发布了这个问题 ,这让我发现了一个很大的问题!

我的数据库中有一个名为Units的十进制列,只要我将列的值设置为NON ZERO,并使用新值SubmitChanges列更新。 如果我尝试将列的值设置为ZERO,则SubmitChanges不会更新列。

data.Units = this.ReadProperty(UnitsProperty); data.UnitPrice = this.ReadProperty(UnitPriceProperty); data.Price = this.ReadProperty(PriceProperty); 

我已经看了一下DataContext日志,我可以看到查询中不包含具有ZERO值的字段。 即使我试图对代码进行硬编码,Linq也会忽略它。

 data.Units = 0; data.UnitPrice = 0; data.Price = 0; 

不用说这是杀了我! 任何想法为什么会这样?

我在SO社区的帮助下想出了我的问题。 我的问题是由于我创建我的实体附加时的事实,列的默认值设置为零,所以当它试图将值分配给零时… LinqToSql说嘿……没有改变,所以我没有更新价值。

我现在在做什么……只是为了让它发挥作用如下:

 ctx.DataContext.InvoiceItems.Attach(data, true); 

这似乎迫使所有值自己写入数据库。 这适用于现在。

我试图用下面的代码重现这个,但对我来说它是有效的。

 using (DataClasses1DataContext ctx = new DataClasses1DataContext()) { var obj = ctx.DecimalColumnTables.First(); Debug.Assert(obj.B != 0); obj.B = 0; ctx.SubmitChanges(); } 

所以我认为你的领域必须有一些特殊的东西导致这一点。 我建议你用你的域模型创建一个这样简单的repro,看看会发生什么。

LINQ to SQL忽略对当前值的更新,因此如果该字段已经为零,则可能看不到任何更新。

关:您使用的OR / M是LINQ to SQL 。 LINQ是.NET中查询function的名称,但LINQ不定义也不实现任何更新逻辑。 所以这个问题与LINQ to SQL有关,而不是LINQ。

明显的问题,但你确定列是在dbml / mapping文件中映射的吗?

另外 – 它是一个计算列吗? (即价格=>单位* unitprice)

我在SO社区的帮助下想出了我的问题。 我的问题是由于我创建我的实体附加时的事实,列的默认值设置为零,所以当它试图将值分配给零时… LinqToSql说嘿……没有改变,所以我没有更新价值。

我现在在做什么……只是为了让它发挥作用如下:

 ctx.DataContext.InvoiceItems.Attach(data, true); 

这似乎迫使所有值自己写入数据库。 这适用于现在。

更多信息……我想出了我的问题……更多的是对LinqToSql缺乏了解……我在做什么:

 private void Child_Update(Invoice parent) { using (var ctx = Csla.Data.ContextManager .GetManager(Database.ApplicationConnection, false)) { var data = new Gimli.Data.InvoiceItem() { InvoiceItemId = ReadProperty(InvoiceItemIdProperty) }; ctx.DataContext.InvoiceItems.Attach(data); if (this.IsSelfDirty) { // Update properties } } } 

我认为这会加载原始值…会发生的是它创建一个具有默认值的新对象…空值,如小数为0,uniqueidentifiers为Guid.Empty等等。

因此,当它更新属性时,它会将Units视为0,并将其设置为零。 好吧,LinqToSql不会将此识别为更改,因此它不会更新该字段。 所以我必须做的是以下内容:

 ctx.DataContext.InvoiceItems.Attach(data, true); 

现在,无论是否真的发生了更改,都会在update语句中生成所有修改。 这工作……似乎有点hackish!

正确的答案是许多人指出使用Attach的特殊重载,它接受一个布尔参数来将其视为已修改,(使用另一个重载的错误,它根本不起作用):

 ctx.DataContext.InvoiceItems.Attach(data, true); 

但请注意,您仍可能需要在“timestamp”类型的表中包含“Version”列。

我有这个问题,我看到的所有建议都没有适用或工作。

但我发现我犯了一个非常简单的错误!

更新属性时,我实际上调用了一个自定义Set方法(因为还有其他一些东西需要更改以响应相关的主要属性)。

经过数小时的头部刮擦,我注意到我的Set方法正在更新私有成员而不是公共属性,即this._Walking = value;

我所要做的就是将其改为this.Walking = value; 这一切都开始奏效了!