[英]Self referencing table Unique and distinct key pair with Ef Core Fluent API
我有一個多對多的自引用表,我希望有一個由兩個外鍵組成的索引(或鍵)。 我還想避免相同的鍵重復和重新排序的鍵,比如
UserParentId xxx UserChildId
0 1 => 好的
0 2 => 好的
1 1 => 不行
2 0 => 不行,因為這個鏈接已經存在(見第二行)
最重要的是,我想使用無序提供的兩個鍵在此索引中進行搜索。 就像是
_dbContext.UserToUsers.Find(userId1, userId2)
不知道 userId1 代表UserParentId還是UserChildId 。
我讀過這個解決方案,它可能是一個很好的通用方法:
model 應該讓UserparentId始終嚴格低於UserChildId ,控制器應該都知道這一點。
盡管如此,我仍然想知道是否已經在 EF CORE 中實現了類似的功能。 Index() 或 HasAlternateKey() 似乎沒有提供我想要的。 任何的想法?
我的代碼:
Model:
public class User
{
public int Id { get; set; }
public virtual ICollection<UserToUser> ChildrenUsers { get; set; }
public virtual ICollection<UserToUser> ParentUsers { get; set; }
}
public class UserToUser
{
public int Id { get; set; }
public int UserParentId { get; set; }
public int UserChildId { get; set; }
public virtual User ChildUser { get; set; }
public virtual User ParentUser { get; set; }
}
然后是我的 Fluent API 代碼:
modelBuilder.Entity<UserToUser>().HasOne(d => d.ChildUser)
.WithMany(p => p.ParentUsers)
.HasForeignKey(d => d.UserParentId);
modelBuilder.Entity<UserToUser>().HasOne(d => d.ParentUser)
.WithMany(p => p.ChildrenUsers)
.HasForeignKey(d => d.UserChildId);
modelBuilder.Entity<UserToUser>()
.HasAlternateKey(x => new {x.UserChildId, x.UserParentId});
關於使用查找:
DbSet 上的 Find 方法使用主鍵值來嘗試查找上下文跟蹤的實體。 如果在上下文中找不到該實體,則將向數據庫發送查詢以在其中查找該實體。 如果在上下文或數據庫中找不到該實體,則返回 Null。
Find
不支持通過替代鍵進行緩存查找,盡管尚未實現,但在未來將不再需要,因為查詢緩存的替代方法將會發展,這意味着您可以編寫一個名為Find
的擴展方法來專門執行您的要求。 看看這個問題和與之相關的問題: DbSet.Find by alternate key or predicate (你不是第一個提出這種請求的人)
因此,您要求 EF 在表中提供多個PrimaryKeys ,但也強制執行一旦用戶是另一個用戶的孩子,他們就不能成為同一用戶的父級,因此所有這些組合的值必須是唯一的:
解決這個問題的另一種方法是認識到對於指定的UserId
您可以在每個User
上使用 Find ,特別是如果您無論如何都想要兩個用戶(因為鏈接表中沒有其他信息,並且兩個用戶對象都可以包含鏈接引用)
var user1 = _dbContext.Users.Find(userId1);
var user2 = _dbContext.Users.Find(userId2);
var link = user1.ChildrenUsers.FirstOrDefault(x => x.UserChildId == userId2)
?? user2.ChildrenUsers.FirstOrDefault(x => x.UserChildId == userId1)
if (link != null)
{
// process when the link exists
}
這將繞過本地緩存,但可以完成工作:
_dbContext.UserToUsers.Where(x => UserParentId == userId1 && UserChildId == userId2
|| UserParentId == userId2 && UserChildId == userId1);
如果您只是進行存在性檢查,則將
Where
更改為Any
,這樣在服務器上運行同樣有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.