【问题标题】:c# linq update all records in databasec# linq 更新数据库中的所有记录
【发布时间】:2009-09-07 23:20:56
【问题描述】:

我正在尝试使用以下代码更新 sql 表中的所有记录,但没有更新数据。有人知道为什么吗?

        using (DataContext db = new DataContext())
        {
            foreach (Item record in db.Items)
            {
                record.Description += "bla";
                db.SubmitChanges();
            }
        }

setter 代码:

[Column(Storage="_Description", DbType="NVarChar(400) NOT NULL", CanBeNull=false)] 
public string Description
{ 
  get { return this._Description; }
  set { 
      if ((this._Description != value))
       { 
         this._Description = value; 
       }
      }
}

【问题讨论】:

  • 您可能希望将标签更改为 LINQ2SQL - 这是一个 LINQ2SQL 问题,而不仅仅是 linq。
  • 您在尝试更新时是否收到任何消息?
  • 没有消息,一切正常。
  • 循环后调用db.GetChangeSet()返回什么?
  • (在循环外使用 SubmitChanges() 调用,如下所示,在调用此之前,并检查返回的 ChangeSet 的更新列表)

标签: c# database linq-to-sql records


【解决方案1】:

出于好奇,看看将 SubmitChanges() 移到循环之外是否会产生影响:

        using (DataContext db = new DataContext())
        {
            foreach (Item record in db.Items)
            {
                record.Description += "bla";   
            }
            db.SubmitChanges();
        }

【讨论】:

  • 不,这样不行。它可能会提高效率。
【解决方案2】:

根据您在 cmets 中发布的 setter 的详细信息,您的 Description 属性尚未正确创建以通知属性更改。该属性是您自己编写的还是由 VS2008 工具生成的?

您的 Item 类(就此而言,所有 Linq to Sql 实体都应实现 INotifyPropertyChanging 和 INotifyPropertyChanged),这将为您提供 PropertyChanging 事件和 PropertyChanged 事件,如果您使用 VS2008 工具,您应该在您的实体类:

    protected virtual void SendPropertyChanging(string propertyName)
    {
        if (this.PropertyChanging != null)
        {
            this.PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }
    }

    protected virtual void SendPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

现在,在您的属性设置器中,您应该使用这些方法来引发所需的事件:

[Column(Name="Description", Storage="_Description",
                  DbType="NVarChar(400) NOT NULL", CanBeNull=false)]   
public string Description
{
     get { return this._Description; }
     set
     {
         if ((this._Description != value))
         {
             this.SendPropertyChanging("Description");
             this._Description = value;
             this.SendPropertyChanged("Description");
         }
     }
 }

我还注意到您没有在列属性中设置 Name 属性,所以添加它以防万一(假设您的列名是“描述”,我将它包含在我的示例中)。

【讨论】:

  • 由于已实现的代码,我看不到任何可以阻止更新的错误,但错误必须在 setter 中。
  • 嗨 Simon,DBML 数据完全是在 VS2008 中创建的。按照您的说明进行操作后,我仍然无法更新任何数据,并且变更集返回 0...
  • 也许我忽略了一些非常基本的东西,比如没有主键或者非常简单的东西......
  • 能否在 SendPropertyChanging 和 SendPropertyChanged 方法中设置断点来检查 DataContext 是否为这些通知注册(即事件属性不为空)?
  • 啊,是的,如果您的表上没有主键,这将解释为什么生成器没有发出 INotifyChanging 和 INotifyChanged 接口。这实际上会阻塞更新以外的任何东西,即插入或删除(我很确定:)所以你会注意到的。您可以通过在 Linq 设计器中的一个表列上将 PrimaryKey 属性设置为 true 来解决此问题(如果您无法修改表)。但是,如果表中最终出现重复数据,这仍然会导致问题。
【解决方案3】:

我会指出您可以在循环关闭后提交更改...这不会解决您的问题,但会有所帮助。

【讨论】:

    【解决方案4】:

    也许你需要提供一个连接字符串。

    using (DataContext db = new DataContext(_MyConnectionString))
    {
        foreach (Item record in db.Items)
        {
            record.Description += "bla";
        }
        db.SubmitChanges();
    }
    

    在不提供连接字符串时,DataContext 出现了一些奇怪的问题。

    【讨论】:

      【解决方案5】:

      我意识到这是一个非常古老的问题,但仍然没有答案。

      Simon Fox 提供的答案在技术上是正确的,BFree 的建议可以节省大量时间。

      然而,如果您的表没有在表中指定主键,则 DBML 对象将不会检测到更改并且不知道如何更新您的记录。

      【讨论】:

        猜你喜欢
        • 2016-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多