LINQ to SQL-отслеживание новых / грязных объектов

есть ли способ определить, был ли объект LINQ еще не вставлен в базу данных (новый) или был изменен с момента последнего обновления (грязный)? Я планирую привязать свой пользовательский интерфейс к объектам 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?

только простой решение, которое я могу придумать, - это установить первичный ключ новых записей на отрицательное значение (мой PKs-это поле идентификатора и будет поэтому установите положительное целое число на INSERT). Это будет работать только для обнаружения новых записей. Он также требует идентификации PKs и требует управления кодом, создающим новый объект.

есть ли лучший способ сделать это? Похоже, LINQ должен внутренне отслеживать состояние этих объектов, чтобы он мог знать, что делать на context.SubmitChanges(). Есть ли способ получить доступ к этому"статусу объекта"?

уточнение Видимо, мой первоначальный вопрос был запутанным. Я не ищу способ вставки или обновления записей. Я ищу способ, учитывая любой объект LINQ, определить, не был ли этот объект вставлен (новый) или был изменен с момента последнего обновления (грязный).

5 ответов


ChangeSet changes = контекст.GetChangeSet();

Если изменений.Вставляет.Содержит (yourObject), то он является новым и будет вставлен, когда SubmitChanges называется

Если изменений.Новинки.Содержит (yourObject), он уже находится в базе данных и будет обновляться на SubmitChanges ()


Я создаю частичный класс для каждого объекта, который создает 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

в каждом объекте данных я реализую свойство IsNew для возврата true, если был установлен PrimaryKey:

/// <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, и если он новый, я вызываю InsertOnSubmit() перед вызовом SubmitChanges().

Это может не быть самый простой способ, но он позволяет все объекты, которые будут сохранены в общем виде.

для каждой таблицы требуется несколько минут для реализации интерфейса, но он позволяет вызывать общий метод Save ().


объект DataContext внутренне отслеживает изменения данных, чтобы оптимизировать SQL-запросы, генерируемые при вызове SubmitChanges ().

Если вы хотите вставить новые объекты в базу данных, а не обновлять существующие объекты, вы должны сделать что-то вроде:

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

теперь, когда вы вызываете SubmitChanges (), он будет генерировать как вставку, так и обновление, если это необходимо. В зависимости от того, как быстро вам нужен первичный ключ для вашего нового объекта, вы можете отправить его правильно чтобы отправить объект, очистите отслеживание изменений и получите новый первичный ключ.


есть интерфейсы INotifyPropertyChanging и INotifyPropertyChanged, которые имеют определенные методы для запуска при вставке, которые позволяют вам знать, если объект загрязнен. Если вы используете SQLMetal, он делает это автоматически. если вы пишете свои собственные классы сущностей, вы должны вручную написать этот сантехнический персонал самостоятельно. Но я не уверен, подходит ли это решение с точки зрения масштабируемости. Я не проверял его. Кажется, что у него могут быть проблемы, так как он запускает событие на машине, которое делает вставку.


вопрос Как добавить свойство "IsDirty" в объект LINQ to SQL? и ответ of ongle, как реализовать свойство IsDirty с помощью события PropertyChanged.

ограничение: он показывает IsDirty как true, если свойство было изменено,но затем отменить.