LINQ to SQL - 跟踪新/脏对象

时间:2009-05-12 18:26:13

标签: c# linq linq-to-sql

有没有办法确定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是一个标识字段,因此将在{{上设置为正整数) 1}})。这仅适用于检测新记录。它还需要身份PK,并需要控制创建新对象的代码。

有更好的方法吗?似乎LINQ必须在内部跟踪这些对象的状态,以便它可以知道在INSERT上做什么。有没有办法访问“对象状态”?

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

5 个答案:

答案 0 :(得分:14)

ChangeSet changes = context.GetChangeSet();

如果changes.Inserts.Contains(yourObject)则为new,将在调用SubmitChanges时插入

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

答案 1 :(得分:2)

我为LINQ创建的每个对象创建一个分部类(Data Objects)并让每个对象实现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,如果是new,我在调用SubmitChanges()之前调用InsertOnSubmit()。

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

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

答案 2 :(得分:1)

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。根据您在新对象上需要主键的速度,您可以立即提交它以提交对象,刷新更改跟踪并获取新的主键。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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