【问题标题】:LINQ to SQL - Tracking New / Dirty ObjectsLINQ to SQL - 跟踪新/脏对象
【发布时间】:2009-05-12 18:26:13
【问题描述】:

有没有办法确定 LINQ 对象是否尚未插入数据库(新)或自上次更新以来已更改(脏)?我计划将我的 UI 绑定到 LINQ 对象(使用 WPF),并需要它根据对象是否已经在数据库中而表现出不同的行为。

MyDataContext context = new MyDataContext();
MyObject obj;
if (new Random().NextDouble() > .5)
    obj = new MyObject();
else
    obj = context.MyObjects.First();
// How can I distinguish these two cases?

我能想到的唯一简单解决方案是将新记录的主键设置为负值(我的 PK 是一个身份字段,因此将在@987654322 上设置为正整数@)。这仅适用于检测新记录。它还需要身份 PK,并且需要控制创建新对象的代码。

有没有更好的方法来做到这一点?似乎 LINQ 必须在内部跟踪这些对象的状态,以便它可以知道在 context.SubmitChanges() 上做什么。有没有办法访问那个“对象状态”?

澄清 显然我最初的问题令人困惑。我不是在寻找插入或更新记录的方法。我正在寻找一种方法,给定任何 LINQ 对象,以确定该对象是否未插入(新)或自上次更新以来已更改(脏)。

【问题讨论】:

    标签: c# linq linq-to-sql


    【解决方案1】:

    ChangeSet 更改 = context.GetChangeSet();

    如果 changes.Inserts.Contains(yourObject) 则它是新的,将在调用 SubmitChanges 时插入

    如果 changes.Updates.Contains(yourObject),它已经在数据库中,并且会在 SubmitChanges() 上更新

    【讨论】:

      【解决方案2】:

      我为每个 LINQ 创建的对象(数据对象)创建一个部分类,并让每个对象实现 IDataObject 接口

      /// <summary>
      /// This interface is used to implement IsNew in all LINQ objects so a Generic Save method 
      /// can be used.
      /// </summary>
      public interface IDataObject
      {
      
          #region Properties
      
      
              #region IsNew
              /// <summary>
              /// Is this a new object
              /// </summary>
              bool IsNew
              {
                  get;
              } 
              #endregion
      
      
          #endregion
      
      } 
      #endregion
      

      在每个数据对象中,如果 PrimaryKey 已设置,我实现 IsNew 属性以返回 true:

      /// <summary>
      /// Is this a new object
      /// </summary>
      public bool IsNew
      {
          get
          {
              // initial value
              bool isNew = (this.CustomerID > 0);
      
              // return value
              return isNew;
          }
      }
      

      然后在我的 DataContext 中,我将 ojbect 转换为 IDataObject,如果它是新的,我在调用 SubmitChanges() 之前调用 InsertOnSubmit()。

      这可能不是最简单的方法,但它允许通用保存所有对象。

      每个表都需要几分钟来实现接口,但它允许调用通用 Save() 方法。

      【讨论】:

        【解决方案3】:

        DataContext 对象在内部跟踪数据的更改,因此它可以优化调用 SubmitChanges() 时生成的 SQL 查询。

        如果您想将新对象插入数据库,而不是更新现有对象,您应该执行以下操作:

        MyDataContext context = new MyDataContext();
        MyObject obj;
        if (new Random().NextDouble() > .5)
        {
            obj = new MyObject();
            context.MyObjects.InsertAllOnSubmit(obj);
        }
        else
            obj = context.MyObjects.First();
        

        现在,当您调用 SubmitChanges() 时,它会在必要时生成 INSERT 和 UPDATE。根据您在新对象上需要主键的速度,您可以立即提交它以提交对象、刷新更改跟踪并获取新的主键。

        【讨论】:

        • 这不是我想要的。我知道如何使用 LINQ 插入/更新。我需要的是确定任何给定 LINQ 对象的状态。
        【解决方案4】:

        INotifyPropertyChanging 和 INotifyPropertyChanged 接口具有在插入时触发的特定方法,让您知道对象是否变脏。如果您使用 SQLMetal,它会自动执行此操作。如果您编写自己的实体类,您必须自己手动编写这些管道人员。但我不确定从可扩展性的角度来看这个解决方案是否合适。我没有测试它。似乎它可能有问题,因为它会在执行插入的机器上触发一个事件。

        【讨论】:

          【解决方案5】:

          问题How can I add an "IsDirty" property to a LINQ to SQL entity?an answerongle,如何使用PropertyChanged事件实现IsDirty属性。

          限制:如果属性已更改,则将 IsDirty 显示为 true,然后撤消。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-07-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-30
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多