[英]Entity Framework Core self referencing table
我有一個名為Item
的類,它引用下一個項目和上一個項目。
public class Item
{
private Item() { }
public Item(string itemName)
{
ItemId = Guid.NewGuid();
ItemName = itemName;
}
public Guid ItemId { get; set; }
public string ItemName { get; set; }
public Guid NextItemId { get; set; }
public virtual Item NextItem { get; set; }
public Guid PreviousItemId { get; set; }
public virtual Item PreviousItem { get; set; }
public Guid GroupId { get; set; }
public virtual Group Group { get; set; }
}
我有另一個名為Group
表,用於對項目進行分組。
public class Group
{
private Group() { }
public Group(string groupName)
{
GroupId = Guid.NewGuid();
GroupName = groupName;
GroupItems = new List<Item>();
}
public void AddGroupItem(Item item)
{
if (Items.Count == 0)
{
Items.Add(item);
}
else
{
item.PreviousItem = Items.Last();
item.PreviousItemId = Items.Last().ItemId;
Items.Last().NextItem = item;
Items.Last().NextItemId = item.ItemId;
Items.Add(item);
}
}
public Guid GroupId { get; set; }
public string GroupName { get; set; }
public virtual IList<GroupItem> GroupItems { get; set; }
}
這是我創建和保存項目及其組的方法。
Group group1 = new Group("first group");
Item item1 = new Item("item 1");
Item item2 = new Item("item 2");
Item item3 = new Item("item 3");
group1.AddItem(item1);
group1.AddItem(item2);
group1.AddItem(item3);
_context.Add(group1);
_context.SaveChanges();
我如何編寫OnModelCreating
來處理對同一個表的兩個引用。
你可以用下一個方法來做。 首先,您應該向模型中添加兩個新屬性public virtual List<Item> ParentNextItems { get; set; }
public virtual List<Item> ParentNextItems { get; set; }
public virtual List<Item> ParentNextItems { get; set; }
和public virtual List<Item> ParentPreviousItems { get; set; }
public virtual List<Item> ParentPreviousItems { get; set; }
public virtual List<Item> ParentPreviousItems { get; set; }
. 所以你的模型將是這樣的
public class Item
{
private Item() { }
public Item(string itemName)
{
ItemId = Guid.NewGuid();
ItemName = itemName;
}
public Guid ItemId { get; set; }
public string ItemName { get; set; }
public Guid? NextItemId { get; set; }
public virtual Item NextItem { get; set; }
public virtual List<Item> ParentNextItems { get; set; }
public Guid? PreviousItemId { get; set; }
public virtual Item PreviousItem { get; set; }
public virtual List<Item> ParentPreviousItems { get; set; }
}
然后你可以用下一種方式配置它
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>()
.HasKey(x => x.ItemId);
modelBuilder.Entity<Item>()
.HasOne(x => x.NextItem).WithMany(x => x.ParentNextItems).HasForeignKey(x => x.NextItemId)
.Metadata.DeleteBehavior = DeleteBehavior.Restrict;
modelBuilder.Entity<Item>()
.HasOne(x => x.PreviousItem).WithMany(x => x.ParentPreviousItems).HasForeignKey(x => x.PreviousItemId)
.Metadata.DeleteBehavior = DeleteBehavior.Restrict;
base.OnModelCreating(modelBuilder);
}
僅此而已。 但是,如果您想通過屬性配置實現相同的目標,則可以跳過void OnModelCreating(ModelBuilder modelBuilder)
更改並編寫下一個模型:
public class Item
{
private Item() { }
public Item(string itemName)
{
ItemId = Guid.NewGuid();
ItemName = itemName;
}
[Key]
public Guid ItemId { get; set; }
public string ItemName { get; set; }
public Guid? NextItemId { get; set; }
[ForeignKey(nameof(NextItemId))]
[InverseProperty(nameof(ParentNextItems))]
public virtual Item NextItem { get; set; }
[ForeignKey(nameof(NextItemId))]
public virtual List<Item> ParentNextItems { get; set; }
public Guid? PreviousItemId { get; set; }
[ForeignKey(nameof(PreviousItemId))]
[InverseProperty(nameof(ParentPreviousItems))]
public virtual Item PreviousItem { get; set; }
[ForeignKey(nameof(PreviousItemId))]
public virtual List<Item> ParentPreviousItems { get; set; }
}
更新您還應該將 PreviousItemId、NextItemId 設為可選(Guid?),我在答案中做了相應的更改。
據我所知,你不能在一次.SaveChanges()
旅行中做到這一點。 創建第二個項目時,您應該已經將第一個項目保存到數據庫中。 (無論如何,這是另一個問題的主題)
但是無論如何,如果您將代碼修改為類似的內容
Group group1 = new Group("first group");
_context.Add(group1);
Item item1 = new Item("item 1");
group1.AddItem(item1);
_context.SaveChanges();
Item item2 = new Item("item 2");
group1.AddItem(item2);
_context.SaveChanges();
Item item3 = new Item("item 3");
group1.AddItem(item3);
_context.SaveChanges();
您可以在一筆交易中完成
您不需要擁有 Collection,因為據我所知,您的目標是創建某種類型的Two Way LinkedList
。 A 能夠通過將.HasOne()
添加到主模型來修復它。
modelBuilder.Entity<Item>().HasOne(x => x.NextItem);
modelBuilder.Entity<Item>().HasOne(x => x.PreviousItem);
public int? DeaultNextStateId { get; set; }
public State DeaultNextState { get; set; }
public virtual ICollection<State> DeaultNextStates { get; set; }
public int? OkNextStateId { get; set; }
public State OkNextState { get; set; }
public virtual ICollection<State> OkNextStates { get; set; }
public int? NotOkNextStateId { get; set; }
public State NotOkNextState { get; set; }
public virtual ICollection<State> NotOkNextStates { get; set; }
modelBuilder.Entity<Models.Workflow.State>()
.HasKey(x => x.Id);
modelBuilder.Entity<Models.Workflow.State>()
.HasOne(x => x.DeaultNextState).WithMany(x => x.DeaultNextStates).HasForeignKey(x => x.DeaultNextStateId)
.Metadata.DeleteBehavior = DeleteBehavior.Restrict;
modelBuilder.Entity<Models.Workflow.State>()
.HasOne(x => x.OkNextState).WithMany(x => x.OkNextStates).HasForeignKey(x => x.OkNextStateId)
.Metadata.DeleteBehavior = DeleteBehavior.Restrict;
modelBuilder.Entity<Models.Workflow.State>()
.HasOne(x => x.NotOkNextState).WithMany(x => x.NotOkNextStates).HasForeignKey(x => x.NotOkNextStateId)
.Metadata.DeleteBehavior = DeleteBehavior.Restrict;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.