昨天晚上我发布了这个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);
这似乎强制所有值都将自己写入数据库。这暂时有效。
答案 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;
我所要做的只是改变这个。走路=价值;这一切都开始起作用了!