I have a class called Item
which references the next item and the previous 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; }
}
I have another table called Group
it is for grouping it items.
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; }
}
Here's how I create and save items and their group.
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();
How do I write the OnModelCreating
to handle the two references to the same table.
You can do it in next way. First of all you should add two new properties to you model public virtual List<Item> ParentNextItems { get; set; }
and public virtual List<Item> ParentPreviousItems { get; set; }
. So your model will be something like this
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; }
}
And than you can configure it in next way
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);
}
That's all. But if you want to achieve the same with attribute configuration, than you can skip void OnModelCreating(ModelBuilder modelBuilder)
changes and just write next model:
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; }
}
Update Also you should make PreviousItemId, NextItemId optional (Guid?), I did corresponding changes in my answer.
And as far as I know, you just can't do it in one .SaveChanges()
trip. When you create your second item you should already have first item saved into database. (anyway this is subject for another question)
But anyway if you modify you code to something like that
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();
You can do it in one transaction
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With