キーは、各エンティティ インスタンスの一意の識別子として機能します。 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; }
}
注
所有エンティティ型では、 キーを定義するためにさまざまなルールが使用されます。
次のように、エンティティの主キーとして 1 つのプロパティを構成できます。
internal class Car
{
[Key]
public string LicensePlate { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
エンティティのキーとして複数のプロパティを構成することもできます。これは複合キーと呼ばれます。 規則では、所有型コレクションのように、特定のケースでのみ複合キーが設定されます。
[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 が呼び出されると、一時値はデータベースによって生成された値に置き換えられます。
Von Bedeutung
キー プロパティにデータベースによって生成された値があり、エンティティの追加時に既定値以外が指定されている場合、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