Состояния объектов и отслеживание изменений
Объекты LINQ to SQL всегда участвуют в определенном состоянии. Например, когда LINQ to SQL создает новый объект, объект находится в Unchanged
состоянии. Новый объект, создаваемый вами самостоятельно, неизвестен DataContext и находится в Untracked
состоянии. После успешного выполнения все объекты, известные SubmitChangesLINQ to SQL, находятся в Unchanged
состоянии. (Единственное исключение представляют объекты, успешно удаленные из базы данных, находящиеся в состоянии Deleted
и не используемые в экземпляре DataContext.)
Состояния объектов
В следующей таблице перечислены возможные состояния объектов LINQ to SQL.
State | Description |
---|---|
Untracked |
Объект, не отслеживаемый LINQ to SQL. Примеры: — объект, не запрашиваемый через текущий DataContext (например, только что созданный объект). — объект, созданный с помощью десериализации — объект, запрашиваемый с помощью другого DataContextобъекта. |
Unchanged |
Объект, извлеченный с использованием текущего DataContext и не измененный после создания. |
PossiblyModified |
Объект, присоединенный к объектуDataContext. Дополнительные сведения см. в разделе "Извлечение данных" и операции CUD в N-уровнях приложений (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
объект доступным путем отслеживаемых объектов в графе. При обработке SubmitChangesLINQ to SQL проходит отслеживаемые объекты и обнаруживает доступные постоянные объекты, которые не отслеживаются. Такие объекты являются кандидатами на вставку в базу данных.
Для классов в иерархии наследования (o
) также задает значение члена, InsertOnSubmitуказанного как дискриминатор, чтобы соответствовать типу объекта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. Несмотря на то, что изменения значения внешнего ключа достаточны для воздействия на обновление базовой строки, необходимо изменить ссылку, чтобы сохранить подключение графа объекта и обеспечить двунаправленную согласованность связей.