![](/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.