C# Linq-to-Sql SubmitChanges 不更新字段......为什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/386211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:28:27  来源:igfitidea点击:

Linq-to-Sql SubmitChanges not updating fields ... why?

c#.netlinqlinq-to-sql

提问by mattruma

I posted this questionyesterday evening, which has led me to discover a hugeproblem!

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

I have a decimal column in my database called Units, anytime I set the value of the column to a NON ZERO, and SubmitChanges the column updates with the new value. If I try to set the value of the column to ZERO, the SubmitChanges does not update the column.

我的数据库中有一个名为 Units 的十进制列,只要我将该列的值设置为非零,并且 SubmitChanges 列就会更新为新值。如果我尝试将列的值设置为零,则 SubmitChanges 不会更新该列。

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

I've taken a look at the DataContext log and I can see that the field with the ZERO value is not included in the query. Even if I try to hard code the change Linq ignores it.

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

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

Needless to say this is killing me! Any ideas why this happening?

不用说这让我很伤心!任何想法为什么会发生这种情况?

Solution

解决方案

I figured out my problem with the help of the SO community. My problem was being caused by the fact when I created my entity to attach, the default value of the column was set to zero, so when it tried to assign the value to zero ... LinqToSql says hey ... nothing changed, so I am not updating the value.

我在 SO 社区的帮助下解决了我的问题。我的问题是由于当我创建要附加的实体时,列的默认值设置为零,因此当它尝试将值分配为零时...我没有更新价值。

What I am doing now ... just to make it work is the following:

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

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

That seems to force all the values to write themselves to the database. This works for now.

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

采纳答案by mattruma

I figured out my problem with the help of the SO community. My problem was being caused by the fact when I created my entity to attach, the default value of the column was set to zero, so when it tried to assign the value to zero ... LinqToSql says hey ... nothing changed, so I am not updating the value.

我在 SO 社区的帮助下解决了我的问题。我的问题是由于当我创建要附加的实体时,列的默认值设置为零,因此当它尝试将值分配为零时...我没有更新价值。

What I am doing now ... just to make it work is the following:

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

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

That seems to force allthe values to write themselves to the database. This works for now.

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

回答by Gaspar Nagy

I have tried to reproduce this with a the following code, but for me it works.

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

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

So I think there must be something special in your domain that causes this. I suggest you to create a such simple repro with your domain model and see what happens.

所以我认为在您的领域中一定有一些特殊的东西导致了这种情况。我建议你用你的域模型创建一个这样简单的重现,看看会发生什么。

LINQ to SQL ignores updates to the current value, so if the field was already zero, you may not see any updates.

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

Off: The OR/M you use is LINQ to SQL. LINQ is the name of the querying capability in .NET, but LINQ does not define nor implement any update logic. So the issue relates to LINQ to SQL, not LINQ.

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

回答by Marc Gravell

Obvious question, but are you sure the column is mapped in the dbml / mapping file?

显而易见的问题,但您确定该列已映射到 dbml / 映射文件中吗?

Also - is it a calculated column? (i.e. price => units * unitprice)

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

回答by mattruma

Some more information ... I figured out my problem ... it's more of a lack of understanding about LinqToSql ... where I am doing:

更多信息......我发现了我的问题......更多的是对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
           }
     }
}

I thought this would load the original values ... what happens is that it creates a new object with default values ... empty values, like 0 for decimals, Guid.Empty for uniqueidentifiers and so on.

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

So when it updates the properties it sees the Units already as 0 and it sets it to zero. Well LinqToSql doesn't recognize this as a change so it doesn't up date the field. So what I have had to do is the following:

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

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

Now all the modifications are generated in the update statement whether there is really a change or not. This works ... seems a bit hackish!

现在所有的修改都在更新语句中生成,无论是否真的有变化。这有效......似乎有点hackish!

回答by mattruma

I had this problem and all the suggestions I'd seen didn't apply or work.

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

But I found I had made a very simple mistake!

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

When updating the property I was actually calling a custom Set method (because there were other things that needed to be changed in response to the main property in question).

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

After hours of head scratching I noticed that my Set method was updating the private member not the public property, i.e. this._Walking = value;

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

All I had to do was change this to this.Walking = value; and it all started to work!

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

回答by yoel halb

The correct answer is as many pointed out to use the special overload of Attach which accepts a boolean parameter to consider it as modified, (make the mistake of using another overload and it simply won't work):

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

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

Note however that you still might need to have a "Version" column in the table of type "timestamp".

但是请注意,您可能仍然需要在“时间戳”类型的表中包含“版本”列。