最初にEFコードを使用して複合キーをマッピングする


115

SQLサーバーテーブル:

SomeId PK varchar(50) not null 
OtherId PK int not null

これをEF 6コードで最初にどのようにマップする必要がありますか?

public class MyTable
{
    [Key]
    public string SomeId { get; set; }

    [Key]
    public int OtherId { get; set; }
}

各列の順序を設定する必要があるいくつかの例を見ましたが、それは必要ですか?

これに関する公式ドキュメントはどこかにありますか?


ですか?SomeIdstringint
Corey Adler

@ IronMan84文字列なので修正します。
loyalflow 2013年

回答:


186

あなたは間違いなく列の順序を入れなければなりません、さもなければ、SQL Serverはどの列が最初に行くのかをどうやって知っているはずですか?コードで行う必要があるのは次のとおりです。

public class MyTable
{
  [Key, Column(Order = 0)]
  public string SomeId { get; set; }

  [Key, Column(Order = 1)]
  public int OtherId { get; set; }
}

このSOの質問もご覧ください。公式ドキュメントが必要な場合は、EF公式ウェブサイトをご覧になることをお勧めします。お役に立てれば。

編集:私はジュリー・ラーマンからのあらゆる種類のEF 6の良さへのリンクを含むブログ投稿を見つけました。ここで必要なものをすべて見つけることができます。


EntityConfigurationを使用してこれをどのように行いますか?結合テーブルのエンティティは実際にはありません...マッピングを設定するための.Map()を使用して、2つのエンティティとその1つにEntityConfigurationがあります。
ミール

31
otherwise how is SQL Server supposed to know which one goes first?-他のすべての列の順序を認識するのと同じ方法でないのはなぜですか?
Davor

1
EFは他の列の順序を認識していません。名前が指定されている限り、任意の順序で列を挿入できます。EFが複合PKの順序を必要とする場合、EFはインデックス付けに関連している必要があります。
シルヴァンガントワ

@Davor EFの作成者はリフレクションを使用してキー/列の順序を推測できたと思いますが、これを行わない場合はパフォーマンスに関する考慮事項がある可能性があります。特にDALでは、いつでもパフォーマンスの低下よりも設計時の特定性を考慮します。
Jacob Stamm

47

エンティティフレームワークを使用して複合主キーをマッピングするには、2つの方法を使用できます。

1)OnModelCreating()メソッドをオーバーライドする

例:以下に示すように、VehicleFeatureという名前のモデルクラスがあります。

public class VehicleFeature
{
    public int VehicleId { get; set; }
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

私のDBContextのコードは、

public class VegaDbContext : DbContext
{
    public DbSet<Make> Makes{get;set;}

    public DbSet<Feature> Features{get;set;}
    public VegaDbContext(DbContextOptions<VegaDbContext> options):base(options)        
    {           

    }
    // we override the OnModelCreating method here.
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<VehicleFeature>().HasKey(vf=> new {vf.VehicleId, vf.FeatureId});
    }
}

2)データ注釈。

public class VehicleFeature
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  
    [Key]
    public int VehicleId { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   
    [Key]
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

詳細については、以下のリンクを参照してください。

1)https://msdn.microsoft.com/en-us/library/jj591617(v=vs.113 ) .aspx

2)EF 6 Fluent Apiを使用して複合一意キーを追加するにはどうすればよいですか?


5
EF CoreのFYI、オプション#2は不可能です。「コンポジットキーはFluent APIを使用してのみ構成できます-規則ではコンポジットキーを設定できず、データアノテーションを使用してキーを構成することはできません。」
Tobias J

7

設定を通じて、これを行うことができます:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

その後、コンテキスト設定で

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Model1>()
            .HasRequired(e => e.Model2)
            .WithMany(e => e.Model1s)
            .HasForeignKey(e => new { e.fk_one, e.fk_two })
            .WillCascadeOnDelete(false);
    }
}

コンテキスト構成のどこに?
チャーリー、

Fluent APIを使用してコードでコンテキストを構成する場合... セクション7。パブリッククラスMyContext:DbContext {protected override void OnModelCreating(DbModelBuilder modelBuilder){modelBuilder.Entity <Model1>().HasRequired(e => e.Model2).WithMany(e => e.Model1s).HasForeignKey(e => new {e.fk_one、e.fk_two}).WillCascadeOnDelete(false); }}
philn5d 2017

dotnetコアでDbModelBuilderではなくModelBuilderを使用する必要があることがわかりました。
kiml42 2018

6

それがトップのグーグル検索結果なので、私はこの質問に追加すると思いました。

コメントで述べたように、EF Coreではアノテーション(キー属性)の使用はサポートされていないため、流暢に行う必要があります。

私はEF6からEF Coreへの大規模な移行に取り組んでいたので、これは不快なものでした。そのため、リフレクションを使用してハックしてKey属性を探し、OnModelCreating中に適用しようとしました。

// get all composite keys (entity decorated by more than 1 [Key] attribute
foreach (var entity in modelBuilder.Model.GetEntityTypes()
    .Where(t => 
        t.ClrType.GetProperties()
            .Count(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute))) > 1))
{
    // get the keys in the appropriate order
    var orderedKeys = entity.ClrType
        .GetProperties()
        .Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute)))
        .OrderBy(p => 
            p.CustomAttributes.Single(x => x.AttributeType == typeof(ColumnAttribute))?
                .NamedArguments?.Single(y => y.MemberName == nameof(ColumnAttribute.Order))
                .TypedValue.Value ?? 0)
        .Select(x => x.Name)
        .ToArray();

    // apply the keys to the model builder
    modelBuilder.Entity(entity.ClrType).HasKey(orderedKeys);
}

私はすべての状況でこれを完全にテストしたわけではありませんが、私の基本的なテストで動作します。これが誰かを助けることを願っています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.