web-dev-qa-db-ja.com

Entity Frameworkで多対多マッピングを作成する方法は?

ここには、契約、メディアなどの2つのエンティティがあります。

public class Media : Entity
{
    public string Name {get; set;}
    public bool Enabled
    *//other properties can be ignored..*
}

public class Contract : Entity
{
    public string Code {get; set;}
    *//other properties can be ignored..*
}

契約には多くのメディアがあり、多対多のようです。

ただしefコードでは最初に、ContractMediaテーブルに3つのフィールドが必要です(ef自動生成)。StartDate、EndDate、Priceなど。これらはMediaエンティティに追加できませんでした。

この場合のマッピング方法は??

46
Kratos

関連付けテーブルの追加データと多対多の関係を作成する場合は、関連付けテーブルをエンティティとして作成する必要があります。純粋な多対多の関係は、エンティティIDを持つ純粋なテーブルにのみ存在します。

あなたの場合、それは次のようになります。

public class Media // One entity table
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Enabled { get; set; }

    public virtual ICollection<ContractMedia> ContractMedias { get; set; }
}

public class Contract // Second entity table
{
    public int Id { get; set; }
    public string Code { get; set }

    public virtual ICollection<ContractMedia> ContractMedias { get; set; }
}

public class ContractMedia // Association table implemented as entity
{
    public int MediaId { get; set; }
    public int ContractId { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public double Price { get; set; }

    public virtual Media Media { get; set; }
    public virtual Contract Contract { get; set; }
}

モデル/エンティティを作成した後、コンテキストで関係を定義する必要があります。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Entity<ContractMedia>()
       .HasKey(c => new { c.MediaId, c.ContractId });

   modelBuilder.Entity<Contract>()
       .HasMany(c => c.ContractMedias)
       .WithRequired()
       .HasForeignKey(c => c.ContractId);

   modelBuilder.Entity<Media>()
       .HasMany(c => c.ContractMedias)
       .WithRequired()
       .HasForeignKey(c => c.MediaId);  
}

また、次のリンクを参照できます。
Fluent APIの追加フィールドを使用した多対多マッピング
Entity Framework CodeFirst追加情報との多対多の関係
アソシエーションテーブルに追加のフィールドを使用して、最初にコードを多数作成します

87
Tomas

Fluent APIを使用せずに@Tomas回答に追加します。

public class Media // One entity table
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<ContractMedia> ContractMedias { get; set; }
}

public class Contract // Second entity table
{
    public int Id { get; set; }

    public string Code { get; set }

    public virtual ICollection<ContractMedia> ContractMedias { get; set; }
}

public class ContractMedia // Association table implemented as entity
{
    [Key]
    [Column(Order = 0)]
    [ForeignKey("Media")]
    public int MediaId { get; set; }

    [Key]
    [Column(Order = 1)]
    [ForeignKey("Contract")]
    public int ContractId { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime EndDate { get; set; }

    public double Price { get; set; }

    public virtual Media Media { get; set; }

    public virtual Contract Contract { get; set; }
}
11
Ogglas