По умолчанию в качестве ключа используется свойство, которое называется Id или [имя_класса]Id. Например:
public class User { public int Id { get; set; } //......................... }
или
public class User { public int UserId { get; set; } //......................... }
Для установки свойства в качестве первичного ключа с помощью аннотаций применяется атрибут [Key]:
using System.ComponentModel.DataAnnotations; public class User { [Key] public int Ident { get; set; } public string? Name { get; set; } }
Для конфигурации ключа с Fluent API применяется метод HasKey():
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } = null!; public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasKey(u => u.Ident); } } public class User { public int Ident { get; set; } public string? Name { get; set; } }
Дополнительно с помощью Fluent API можно настроить имя ограничения, которое задается для первичного ключа. Для этого применяется метод HasName():
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasKey(u => u.Ident).HasName("UsersPrimaryKey"); }
С помощью Fluent API можно создать составной ключ из нескольких свойств:
public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasKey(u => new { u.PassportSeria, u.PassportNumber}); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=efbasicsappdb;Trusted_Connection=True;"); } } public class User { public string? PassportNumber { get; set; } public string? PassportSeria { get; set; } public string? Name { get; set; } }
Составной ключ можно создать только с помощью Fluent API. Применение подобного ключа:
using (ApplicationContext db = new ApplicationContext()) { db.Users.Add(new User { PassportSeria = "1234", PassportNumber = "345678", Name="Tom" }); db.Users.Add(new User { PassportSeria = "1234", PassportNumber = "345679", Name="Bob" }); db.SaveChanges(); var users = db.Users.ToList(); foreach (var u in users) Console.WriteLine($"{u.Name} : {u.PassportSeria} {u.PassportNumber}"); }
На уровне базы данных в случае с SQLite будет создаваться следующая таблица:
CREATE TABLE "Users" ( "PassportNumber" TEXT NOT NULL, "PassportSeria" TEXT NOT NULL, "Name" TEXT, CONSTRAINT "PK_Users" PRIMARY KEY("PassportSeria","PassportNumber") );
Альтернативные ключи представляют свойства, которые также, как и первичный ключ, должны иметь уникальное значение. В то же время альтернативные ключи не являются первичными. На уровне базы данных это выражается в установке для соответствующих столбцов ограничения на уникальность.
Для установки альтернативного ключа используется метод HasAlternateKey():
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } = null!; public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasAlternateKey(u => u.Passport); } } public class User { public int Id { get; set; } public string? Name { get; set; } public string? Passport { get; set; } }
В данном случае свойство Passport (серия и номер паспорта) будет альтернативным ключом. Созданная таблица Users в случае SQLite будет описываться следующим SQL-скриптом:
CREATE TABLE "Users" ( "Id" INTEGER NOT NULL, "Name" TEXT, "Passport" TEXT NOT NULL, CONSTRAINT "AK_Users_Passport" UNIQUE("Passport"), CONSTRAINT "PK_Users" PRIMARY KEY("Id" AUTOINCREMENT) );
Альтернативные ключи также могут быть составными:
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } = null!; public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasAlternateKey(u => new { u.Passport, u.PhoneNumber }); } } public class User { public int Id { get; set; } public string? Name { get; set; } public string? Passport { get; set; } public string? PhoneNumber { get; set; } }
В этом случае в SQLite будет создаваться следующая таблица:
CREATE TABLE "Users" ( "Id" INTEGER NOT NULL, "Name" TEXT, "Passport" TEXT NOT NULL, "PhoneNumber" TEXT NOT NULL, CONSTRAINT "AK_Users_Passport_PhoneNumber" UNIQUE("Passport","PhoneNumber"), CONSTRAINT "PK_Users" PRIMARY KEY("Id" AUTOINCREMENT) );