Работа с ключами сущностей (платформа Entity Framework)

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

Когда объект возвращается запросом объекта, платформа Entity Framework материализует объект сущности. Кроме того, материализуется ключ сущности в экземпляре класса EntityKey. Доступ к EntityKey производится через свойство EntityKey объекта, реализующего интерфейс IEntityWithKey. Класс EntityObject, который является базовым для всех классов данных, создаваемых средствами модели модель EDM (сущностная модель данных) , также реализует интерфейс IEntityWithKey.

Dd283139.note(ru-ru,VS.100).gifПримечание
Платформа Entity Framework не требует обязательной реализации интерфейса IEntityWithKey пользовательским классом данных.

Построение и использование объекта EntityKey

Объект EntityKey состоит из свойств EntitySetName и EntityContainerName, а также массива из одной или нескольких пар «ключ-значение». Пара «ключ-значение» состоит из имени свойства и его значения. Пары «ключ-значение» передаются в виде объектов EntityKeyMember в свойстве EntityKeyValues.

Dd283139.note(ru-ru,VS.100).gifПримечание
При использовании одного из конструкторов EntityKey строковое значение, передаваемое параметру qualifiedEntitySetName, представляет собой имя EntitySetName, предваряемое именем EntityContainerName, например: EntityContainerName.EntitySetName.

Можно также с помощью метода CreateEntityKey объекта ObjectContext получить EntityKey для отсоединенного объекта. Если объект не имеет допустимого ключа, то контекст объекта создает для заданного объекта новый экземпляр EntityKey. Дополнительные сведения см. в разделе Как создать EntityKey (платформа Entity Framework).

Поскольку ключ сущности однозначно определяет эту сущность, можно создать сущность, содержащую только ключ, и присоединить объект к контексту, даже если оставшиеся значения объекта не были извлечены из источника данных. Дополнительные сведения см. в разделе Как присоединить связанные объекты (платформа Entity Framework). Ключ сущности может быть также использован для получения объекта — как из контекста объекта, так и из источника данных. Дополнительные сведения см. в разделе Как вернуть конкретный объект с помощью его ключа (платформа Entity Framework).

Ключи сущностей фиксированной длины

Платформа Entity Framework проводит разрешение идентичности на основе значения EntityKey, соответствующего первичному ключу в базе данных. Если запрос возвращает объект со значением EntityKey, уже существующим в контексте ObjectContext, то новый объект не создается. Если при работе со столбцами фиксированного размера в базе данных выполняется сохранение значений, размер которых меньше, чем указано в базе данных, то некоторые базы данных дополняют типы фиксированного размера нулями или пробелами. SQL Server дополняет строковые типы фиксированного размера конечными пробелами. Это может привести к проблемам разрешения идентификаторов, если типы фиксированного размера (например, binary и char) используются в качестве первичных ключей.

Рассмотрим следующий пример. Таблица Product в качестве первичного ключа использует столбец фиксированной длины 10. Объект Product с ключом EntityKey AB100 создается и добавляется в ObjectContext. Когда объект сохраняется в базе данных, ключ дополняется конечными пробелами, поскольку столбец имеет фиксированный размер, а сохраняемое значение имеет размер меньше, чем размер в базе данных. Последующий запрос к объекту с ключом EntityKey AB100 вернет объект с другим значением ключа EntityKey AB100, дополненный завершающими пробелами, поскольку SQL Server ищет соответствие строке AB100, дополненной пробелами. Entity Framework не выполняет усечение и дополнение значений свойств. В результате к контексту ObjectContext будет добавлен новый объект (с ключом EntityKey AB100, дополненным завершающими пробелами).

Product p1= new Product 
{ 
    ProductID = "AB100", 
    Description = "New product" 
}; 
// An object with EntityKey "AB100" is added to ObjectContext.  ctx.Products.AddObject(p1); 
// The object is saved in the database with a primary key of 
// "AB100     " because the column is of a fixed size.  ctx.SaveChanges();
// When a query is executed for an object with key "AB100", SQL Server // matches the key to "AB100     ".  The result is that a new object 
// with EntityKey "AB100     " is added to ObjectContext.  Product p2 = ctx.Products.First(p => p.ProductCode == "AB100");  

Чтобы избежать этого нежелательного явления, выполните одно из следующих действий.

  • Вместо типов фиксированной длины используйте в базе данных тип переменной длины.

  • Дополняйте значение EntityKey завершающими пробелами или нулями на клиенте. Для дополнения строки пробелами можно использовать метод PadRight.

Ключи сущностей и добавленные объекты

При создании новой сущности платформа Entity Framework определяет временный ключ и присваивает свойству IsTemporary значение true. При вызове метода SaveChanges платформа Entity Framework назначает постоянный ключ и присваивает свойству IsTemporary значение false.

Если значением соответствующего столбца является сущность, созданная в базе данных, задайте для атрибута StoreGeneratedPattern элемента Property сущности в модели хранения значение Identity. Когда модель данных формируется средствами работы с моделью модель EDM (сущностная модель данных) из существующего источника данных, атрибут StoreGeneratedPattern добавляется к каждому элементу Элемент Property (CSDL), представляющему сущность или вычисляемый столбец в источнике данных. Платформа Entity Framework заменяет значение свойства во временном ключе значением идентификатора, созданным источником данных после вызова метода SaveChanges.

Далее подробно описан внутренний процесс замены временного ключа постоянным, содержащим значения, созданные сервером.

  1. Конструируется объект сущности.

    В этот момент все ключевые свойства имеют значения по умолчанию, null или 0.

  2. Новый объект добавляется к контексту ObjectContext либо вызовом метода AddObject объекта ObjectContext или ObjectSet, либо добавлением объекта в коллекцию объектов на стороне «много» связи «один ко многим».

    В этот момент Entity Framework формируемый временный ключ, используемый для хранения объектов в ObjectStateManager.

  3. Вызывается метод SaveChanges объекта ObjectContext.

    Платформа Entity Framework создает оператор INSERT и выполняет его на источнике данных.

  4. Если операция INSERT выполнена успешно, то сформированные сервером значения сохраняются в ObjectStateEntry.

  5. ObjectStateEntry изменяет объект с помощью значения, сформированного на сервере.

  6. При вызове метода AcceptChanges объекта ObjectStateEntry новые значения, сформированные на сервере, используются для вычисления EntityKey.

    Dd283139.note(ru-ru,VS.100).gifПримечание
    Метод AcceptChanges вызывается автоматически после выполнения метода SaveChanges либо при вызове метода SaveChanges с флагом AcceptAllChangesAfterSave.

  7. Объект ObjectStateManager заменяет все экземпляры временного ключа новым постоянным ключом.

значения свойств GUID

Платформа Entity Framework поддерживает свойства сущностей, возвращающие тип Guid для обеспечения уникальности.

Entity Framework поддерживает формируемые на сервере значения идентификаторов GUID, однако поставщик должен иметь возможность возвращать формируемые сервером значения идентификаторов после вставки строк. Начиная с версии SQL Server 2005, база данных SQL Server может возвращать формируемый сервером тип идентификатора GUID через предложение OUTPUT. Если поставщик не поддерживает эквивалент предложения OUTPUT, то значения GUID для новых объектов нужно формировать на стороне клиента. Для этого рекомендуется обрабатывать событие SavingChanges, чтобы новое значение GUID создавалось для любого объекта сущности в состоянии Added. Дополнительные сведения см. в разделе Как выполнять правила бизнес-логики при сохранении изменений (платформа Entity Framework).

При создании или обновлении модели данных с помощью Entity Data Model Wizard или Update Model Wizard свойства GUID типов сущностей автоматически формируются для столбцов uniqueidentifier типа в источнике данных. Источник данных может использовать для хранения значений GUID 16-байтные двоичные столбцы. Поскольку средства формируют двоичное свойство для каждого двоичного столбца в источнике данных, придется обновить сопоставление таких столбцов со свойствами GUID вручную, путем изменения EDMX-файла. Дополнительные сведения см. в разделе How to: Map a GUID Property to a Binary Column.

В этом разделе

Как создать EntityKey (платформа Entity Framework)

См. также

Задачи

Как создать EntityKey (платформа Entity Framework)

Другие ресурсы

Entity Data Model Tools