Ключи
Ключ служит уникальным идентификатором для каждого экземпляра сущности. Большинство сущностей в EF имеют один ключ, который сопоставляется с понятием первичного ключа в реляционных базах данных (для сущностей без ключей см . раздел "Без ключей"). Сущности могут иметь дополнительные ключи за пределами первичного ключа (дополнительные сведения см. в разделе "Альтернативные ключи ").
Настройка первичного ключа
По соглашению свойство с именем Id
или <type name>Id
будет настроено в качестве первичного ключа сущности.
internal class Car
{
public string Id { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
internal class Truck
{
public string TruckId { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
Примечание.
Типы сущностей, принадлежащие типы сущностей, используют разные правила для определения ключей.
Вы можете настроить одно свойство в качестве первичного ключа сущности следующим образом:
internal class Car
{
[Key]
public string LicensePlate { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
Можно также настроить несколько свойств, чтобы быть ключом сущности. Это называется составным ключом. Соглашения настраивают только составной ключ в определенных случаях, например для коллекции собственных типов.
Примечание.
Атрибут [PrimaryKey]
появился в EF Core 7.0. Используйте API Fluent в более ранних версиях.
[PrimaryKey(nameof(State), nameof(LicensePlate))]
internal class Car
{
public string State { get; set; }
public string LicensePlate { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
Создание ценностей
Для не составных числовых и первичных ключей GUID EF Core настраивает для вас создание значений по соглашению. Например, числовой первичный ключ в SQL Server автоматически настраивается как столбец IDENTITY. Дополнительные сведения см . в документации по генерации значений и рекомендациям по конкретным стратегиям сопоставления наследования.
Имя первичного ключа
По соглашению для первичных ключей реляционных баз данных создаются с именем PK_<type name>
. Имя ограничения первичного ключа можно настроить следующим образом:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasKey(b => b.BlogId)
.HasName("PrimaryKey_BlogId");
}
Ключевые типы и значения
Хотя EF Core поддерживает использование свойств любого примитивного типа в качестве первичного ключа, включая string
Guid
и byte[]
другие, не все базы данных поддерживают все типы в качестве ключей. В некоторых случаях значения ключей можно преобразовать в поддерживаемый тип автоматически, в противном случае преобразование должно быть указано вручную.
Свойства ключей всегда должны иметь значение, отличное от по умолчанию при добавлении новой сущности в контекст, но некоторые типы создаются базой данных. В этом случае EF попытается создать временное значение при добавлении сущности в целях отслеживания. После вызова SaveChanges временное значение будет заменено значением, созданным базой данных.
Важно!
Если свойство ключа имеет свое значение, созданное базой данных, и значение, отличное от по умолчанию, указывается при добавлении сущности, EF предполагает, что сущность уже существует в базе данных и попытается обновить ее вместо вставки нового. Чтобы избежать этого, отключите создание значений или узнайте , как указать явные значения для созданных свойств.
Альтернативные ключи
Альтернативный ключ служит альтернативным уникальным идентификатором для каждого экземпляра сущности в дополнение к первичному ключу; его можно использовать в качестве целевого объекта связи. При использовании реляционной базы данных это сопоставляется с понятием уникального индекса или ограничения для альтернативных ключевых столбцов и одного или нескольких ограничений внешнего ключа, ссылающихся на столбцы.
Совет
Если вы просто хотите применить уникальность в столбце, определите уникальный индекс, а не альтернативный ключ (см . индексы). В EF альтернативные ключи доступны только для чтения и предоставляют дополнительную семантику по уникальным индексам, так как они могут использоваться в качестве целевого объекта внешнего ключа.
Альтернативные ключи обычно отображаются при необходимости и не нужно настраивать их вручную. По соглашению альтернативный ключ вводится при определении свойства, которое не является первичным ключом в качестве целевого объекта связи.
internal class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasOne(p => p.Blog)
.WithMany(b => b.Posts)
.HasForeignKey(p => p.BlogUrl)
.HasPrincipalKey(b => b.Url);
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public string BlogUrl { get; set; }
public Blog Blog { get; set; }
}
Можно также настроить одно свойство в качестве альтернативного ключа:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasAlternateKey(c => c.LicensePlate);
}
Можно также настроить несколько свойств в качестве альтернативного ключа (известного как составной альтернативный ключ):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasAlternateKey(c => new { c.State, c.LicensePlate });
}
Наконец, по соглашению индекс и ограничение, введенные для альтернативного ключа, будут названы AK_<type name>_<property name>
(для составных альтернативных ключей <property name>
становится разделенный подчеркиванием список имен свойств). Можно настроить имя индекса альтернативного ключа и уникального ограничения:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.HasAlternateKey(c => c.LicensePlate)
.HasName("AlternateKey_LicensePlate");
}