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

时间:2008-12-22 12:57:08

标签: c# .net linq linq-to-sql

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

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

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

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

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

毋庸置疑这是在杀我!有没有想过为什么会这样?

解决方案

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

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

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

这似乎强制所有值都将自己写入数据库。这暂时有效。

6 个答案:

答案 0 :(得分:3)

我尝试使用以下代码重现这一点,但对我而言,它有效。

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中查询功能的名称,但LINQ不定义也不实现任何更新逻辑。所以问题与LINQ to SQL有关,而不是LINQ。

答案 1 :(得分:2)

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

另外 - 它是一个计算列吗? (即price =&gt; units * unitprice)

答案 2 :(得分:2)

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

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

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

这似乎迫使所有值将自己写入数据库。这暂时有效。

答案 3 :(得分:2)

更多信息......我想出了我的问题......更多的是对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!

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

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

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

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

经过几个小时的抓挠,我注意到我的Set方法正在更新私有成员而不是公共财产,即this._Walking = value;

我所要做的只是改变这个。走路=价值;这一切都开始起作用了!