Hoe maak je een veel-op-veel-toewijzing in Entity Framework?

Hier is het geval, ik heb 2 entiteiten, zoals Contract、Media。

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..*
}

Contract heeft veel media, het lijkt erop dat het er veel te veel zijn.

Maar!! bij ef code eerst, heb ik nog 3 velden nodig in de ContractMedia-tabel (ef automatisch gegenereerd).
zoals StartDate, EndDate en Prijs. deze kunnen niet worden toegevoegd in Media-entiteit.

Hoe in kaart brengen in dit geval??


Antwoord 1, autoriteit 100%

Als u veel-op-veel-relaties wilt maken met aanvullende gegevens in een associatietabel, moet u de associatietabel als entiteit maken. De pure veel-op-veel-relatie is alleen in pure tabel met entiteits-ID’s.

In jouw geval zal het zijn:

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; }
}

En nadat u modellen/entiteiten hebt gemaakt, moet u relaties in context definiëren:

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);  
}

U kunt ook naar deze links verwijzen:
Veel tot veel mapping met extra velden in Fluent API
Entity Framework CodeFirst Many to Many-relatie met aanvullende informatie
Maak eerst code, veel tot veel, met extra velden in associatietabel


Antwoord 2, autoriteit 24%

Toevoegen aan @Tomas-antwoord zonder Fluent API te hoeven gebruiken.

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; }
}

EF Core moet Fluent API gebruiken, maar het ziet er als volgt uit:

internal class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> options)
        : base(options)
    {
    }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Tag> Tags { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasMany(p => p.Tags)
            .WithMany(p => p.Posts)
            .UsingEntity<PostTag>(
                j => j
                    .HasOne(pt => pt.Tag)
                    .WithMany(t => t.PostTags)
                    .HasForeignKey(pt => pt.TagId),
                j => j
                    .HasOne(pt => pt.Post)
                    .WithMany(p => p.PostTags)
                    .HasForeignKey(pt => pt.PostId),
                j =>
                {
                    j.Property(pt => pt.PublicationDate).HasDefaultValueSql("CURRENT_TIMESTAMP");
                    j.HasKey(t => new { t.PostId, t.TagId });
                });
    }
}
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public ICollection<Tag> Tags { get; set; }
    public List<PostTag> PostTags { get; set; }
}
public class Tag
{
    public string TagId { get; set; }
    public ICollection<Post> Posts { get; set; }
    public List<PostTag> PostTags { get; set; }
}
public class PostTag
{
    public DateTime PublicationDate { get; set; }
    public int PostId { get; set; }
    public Post Post { get; set; }
    public string TagId { get; set; }
    public Tag Tag { get; set; }
}

Bron:

https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple -key#join-entity-type-configuration

Other episodes