Состояния объектов и Change-Tracking

Объекты LINQ to SQL всегда участвуют в определенном состоянии. Например, когда LINQ to SQL создает новый объект, объект находится в Unchanged состоянии. Новый объект, создаваемый вами самостоятельно, неизвестен DataContext и находится в Untracked состоянии. После успешного выполнения SubmitChanges, все объекты, известные как LINQ to SQL, находятся в состоянии Unchanged. (Единственное исключение составляют те, которые успешно удалены из базы данных, находящиеся в состоянии Deleted и непригодные в этом экземпляре DataContext.)

Состояния объектов

В следующей таблице перечислены возможные состояния объектов LINQ to SQL.

Государство Описание
Untracked Объект, не отслеживаемый LINQ to SQL. Ниже приведены примеры.

— объект, не запрашиваемый через текущий DataContext (например, только что созданный объект).
— объект, созданный с помощью десериализации
— объект, запрашиваемый с помощью другого DataContextобъекта.
Unchanged Объект, полученный с помощью текущего DataContext и не известно, что был изменен после его создания.
PossiblyModified Объект, присоединенный к объекту DataContext. Дополнительные сведения см. в разделе "Извлечение данных и операции CUD в многоуровневых приложениях (LINQ to SQL).
ToBeInserted Объект не извлечен с использованием текущего DataContext. Это вызывает INSERT в базе данных во время SubmitChanges.
ToBeUpdated Известно, что объект был изменен с момента его изъятия. Это вызывает UPDATE в базе данных во время SubmitChanges.
ToBeDeleted Объект, помеченный для удаления, вызывая базу данных DELETE во время SubmitChanges.
Deleted Объект, удаленный в базе данных. Это состояние является окончательным и не разрешает дополнительные переходы.

Вставка объектов

Вы можете явно запросить Inserts с помощью InsertOnSubmit. Кроме того, LINQ to SQL может выводить Inserts , найдя объекты, подключенные к одному из известных объектов, которые должны быть обновлены. Например, если вы добавляете объект Untracked в EntitySet<TEntity> или назначаете EntityRef<TEntity> объекту Untracked, вы делаете Untracked объект достижимым через отслеживаемые объекты в графе. При обработке SubmitChanges LINQ to SQL проходит отслеживаемые объекты и обнаруживает достижимые постоянные объекты, которые не отслеживаются. Такие объекты являются кандидатами на вставку в базу данных.

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

Это важно

Объект, добавленный в Table, отсутствует в кэше удостоверений. Кэш идентичности отражает только то, что извлекается из базы данных. После вызова InsertOnSubmit, добавленная сущность не отображается в запросах к базе данных, пока SubmitChanges не завершится успешно.

Удаление объектов

Вы отмечаете отслеживаемый объект o для удаления, вызывая DeleteOnSubmit(o) на соответствующем Table<TEntity>. LINQ to SQL считает удаление объекта из EntitySet<TEntity> операцией обновления, в ходе которой соответствующее значение внешнего ключа устанавливается равным NULL. Цель операции (o) не удаляется из таблицы. Например, cust.Orders.DeleteOnSubmit(ord) указывает обновление, в котором связь между cust и ord отрезается, задав внешний ключ ord.CustomerID значение NULL. Это не приводит к удалению строки, соответствующей ord.

LINQ to SQL выполняет следующую обработку при удалении объекта (DeleteOnSubmit) из таблицы:

  • Когда вызывается SubmitChanges, для этого объекта выполняется операция DELETE.

  • Удаление не распространяется на связанные объекты независимо от того, загружаются ли они. В частности, связанные объекты не загружаются для обновления свойства связи.

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

Можно вызывать DeleteOnSubmit только на объект, который отслеживается с помощью DataContext. Для объекта Untracked необходимо вызвать Attach перед тем, как вызвать DeleteOnSubmit. Вызов DeleteOnSubmit на объекте Untracked вызывает исключение.

Замечание

При удалении объекта из таблицы LINQ to SQL получает указание сгенерировать соответствующую команду SQL DELETE в момент SubmitChanges. Это действие не удаляет объект из кэша или не распространяет удаление на связанные объекты.

Чтобы восстановить id удаленный объект, используйте новый DataContext экземпляр. Для очистки связанных объектов можно использовать функцию каскадного удаления базы данных или удалить связанные объекты вручную.

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

Обновление объектов

Вы можете обнаружить Updates , наблюдая за уведомлениями об изменениях. Уведомления предоставляются через событие PropertyChanging в установщиках свойств. Когда LINQ to SQL уведомляется о первом изменении объекта, он создает копию объекта и рассматривает объект кандидатом для создания инструкции Update .

Для объектов, которые не реализуют INotifyPropertyChanging, LINQ to SQL поддерживает копию значений, которые объекты имели при первой материализации. При вызове SubmitChangesLINQ to SQL сравнивает текущие и исходные значения, чтобы определить, был ли объект изменен.

Для обновлений связей ссылка от дочернего элемента к родительскому элементу (т. е. ссылка, соответствующая внешнему ключу), считается основным источником данных. Ссылка в обратном направлении (то есть от родительского к дочернему) — необязательная. Классы связей (EntitySet<TEntity> и EntityRef<TEntity>) гарантируют согласованность двунаправленных ссылок для связей "один ко многим" и "один к одному". Если объектная модель не использует EntitySet<TEntity> или EntityRef<TEntity>, и если обратная ссылка имеется, вы несете ответственность за поддержание ее соответствия с прямой ссылкой при обновлении отношения.

Если вы обновляете как необходимую ссылку, так и соответствующий внешний ключ, вы должны убедиться, что они соответствуют друг другу. Исключение InvalidOperationException возникает, если они не синхронизированы во время вызова SubmitChanges. Хотя изменения значений внешнего ключа достаточны для инициирования обновления базовой строки, следует изменить ссылку, чтобы обеспечить подключение графа объектов и двунаправленную согласованность отношений.

См. также