![](/img/trans.png)
[英]How can I create a composite primary key consisting of foreign keys to two tables in Entity Framework?
[英]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.