繁体   English   中英

实体框架对使用复合主键的表形成虚拟 collections

[英]Entity Framework forming virtual collections to tables that use composite primary keys

在实体框架中,如何将虚拟集合链接到另一个使用复合键的表? 这是两个示例表:

public abstract class Table1
{
    public Guid EventId { get; set; }
    public string EventName { get; set; }

    public virtual ICollection<Table2> Table2 { get; private set; }
}

public abstract class Table2
{
    public Guid EventId { get; set; }
    public string DetailKey { get; set; }
    public string DetailValue { get; set; }

    public virtual Table1 Table1 { get; set; }
}

意思是在Table1中添加一个事件,然后使用一对多的关系,向Table2添加N行。 表 1 中的 Guid EventId为 PK,表 2 中的 PK 由EventId + DetailKey组合而成,即 Table2 中可能有 N 行与 Table1 中对应的EventId相关。 Table2 也有一个EventId到 Table1 的 EventId 的 FK。

Table1 的 map 文件如下所示(部分):

public override void ConfigureImp(EntityTypeBuilder<Table1> builder)
{
    base.ConfigureImp(builder);

    // Relationships            
    builder.HasMany(t => t.Table2)
          .WithOne(t => t.Table1)
          .HasForeignKey(x => new { x.EventId, x.DetailKey });
}

Table2 的 map 文件如下所示(部分):

public override void ConfigureImp(EntityTypeBuilder<Table2> builder)
{
    base.ConfigureImp(builder);

    // Relationships
    builder.HasOne(t => t.Table1)
         .WithMany(t => t.Table2)
         .HasForeignKey(x => x.EventId)
         .OnDelete(DeleteBehavior.Restrict)
         .IsRequired();
}

让我们添加一些数据,比如向 Table1 添加 1 行 EventId FOO ,向 Table2 添加 5 行,其中 Table2 中的每一行具有相同的 EventId(以满足 FK)但唯一的 DetailKey(以满足复合键)。 完成此操作后,我运行如下查询:

Table1 target = db.Table1
                    .Include(x => x.Table2)
                    .SingleOrDefault(x => x.EventId.Equals("FOO"));

执行此操作并检查target的内容(例如,作为断点)我希望看到来自 Table1 的详细信息,以及来自 Table2 的所有 5 行,因为.Include 但是,我实际上得到的只是 Table2 中的一行,无论哪一行先出现在表中(这意味着它可以随着该EventId的其他行添加到 Table2 中而改变。

关于为什么我没有使用上面针对target显示的查询从 Table2 中获取所有相应行的任何想法? 谢谢你。

不需要两次声明关系,外键就是EventId。

例如


public  class Event
{
    public Guid EventId { get; set; }
    public string EventName { get; set; }

    public virtual ICollection<EventDetail> Details { get; private set; }
}
public class EventDetail
{
    public Guid EventId { get; set; }
    public string DetailKey { get; set; }
    public string DetailValue { get; set; }

    public virtual Event Event{ get; set; }
}


protected override void OnModelCreating(ModelBuilder modelBuilder)
{


     modelBuilder.Entity<EventDetail>()
         .HasOne(t => t.Event)
         .WithMany(t => t.Details)
         .HasForeignKey(x => x.EventId)
         .OnDelete(DeleteBehavior.Restrict)
         .IsRequired();

    modelBuilder.Entity<EventDetail>().HasKey(e => new { e.EventId, e.DetailKey });

    base.OnModelCreating(modelBuilder);
}

你可以只添加必要的属性,你应该能够避免你写的方法:

public  class Event
{
    [Key]
    public virtual Guid EventId { get; set; }
    public virtual string EventName { get; set; }
    public virtual ICollection<EventDetail> Details { get; set; }
}
public class EventDetail
{
    [Key, Column(Order = 0)]
    [ForeignKey("EventId")]
    public virtual Guid EventId { get; set; }
    [Key, Column(Order = 1)]
    public virtual string DetailKey { get; set; }
    public virtual string DetailValue { get; set; }
    public virtual Event Event{ get; set; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM