キー
キーは、各エンティティ インスタンスの一意の識別子として機能します。 EF のほとんどのエンティティには 1 つのキーがあり、これはリレーショナルデータベースの "主キー" の概念にマップされます (キーのないエンティティについてはキーなしエンティティに関する記事を参照してください)。 エンティティには、主キーに加えて追加のキーを含めることができます (詳細については、「代替キー」を参照してください)。
主キーの構成
慣例により、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; }
}
Note
所有エンティティ型では異なる規則を使用してキーを定義します。
次のように、1 つのプロパティをエンティティの主キーとして構成できます。
internal class Car
{
[Key]
public string LicensePlate { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
また、1 つのエンティティのキーとして複数のプロパティを構成することもでき、これは複合キーと呼ばれます。 規則では、所有型コレクションのように、特定のケースでのみ複合キーが設定されます。
Note
[PrimaryKey]
属性は EF Core 7.0 で導入されました。 古いバージョンでは Fluent API を使用してください。
[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 では、そのエンティティがデータベースに既に存在していると見なされ、新しいエンティティを挿入する代わりにそれを更新しようとします。 これを回避するには、値の生成をオフにするか、生成されるプロパティに明示的な値を指定する方法に関する記事を参照してください。
代替キー
代替キーは、主キーに加えて各エンティティ インスタンスの代替一意識別子として機能し、リレーションシップのターゲットとして使用できます。 リレーショナル データベースを使用する場合、これは代替キー列の一意のインデックスおよび制約と、その列を参照する 1 つ以上の外部キー制約の概念にマップされます。
ヒント
列に一意性を強制するだけの場合は、代替キーではなく一意のインデックスを定義します (「インデックス」を参照してください)。 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; }
}
また、1 つのプロパティを代替キーにするように構成することもできます。
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");
}
.NET