我正在尝试使用Entity Framework 4遵循DDD Repository模式。但是我在保存聚合根的集合属性更改时遇到了问题。请参考我的下面的类。Item是我的聚合根,其中包含SubItem实体的集合。
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public ICollection<SubItem> SubItems { get; private set; }
public Item()
{
this.SubItems = new HashSet<SubItem>();
}
}
public class SubItem
{
public int ItemId { get; set; }
public int SubItemId { get; set; }
public string Name { get; set; }
}
接下来,我为我的聚合根类定义了一个仓储接口。
public interface IItemRespository
{
Item Get(int id);
void Add(Item i);
void Save(Item i);
}
现在这是我的DbContext类,它设置了EF映射。
public class ItemContext : System.Data.Entity.DbContext
{
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>().HasKey(i => i.ItemId);
modelBuilder.Entity<Item>().Property(i => i.Name);
modelBuilder.Entity<Item>().HasMany(i => i.SubItems)
.WithRequired()
.HasForeignKey(si => si.ItemId);
modelBuilder.Entity<SubItem>().HasKey(i => i.SubItemId);
modelBuilder.Entity<SubItem>().Property(i => i.Name);
}
}
最终这是我使用DBContext实现的IRepository
public class Repository : IItemRespository
{
public void Save(Item i)
{
using (var context = new ItemContext())
{
context.Set<Item>().Attach(i);
context.SaveChanges();
}
}
public Item Get(int id)
{
using (var context = new ItemContext())
{
var result = (from x in context.Set<Item>() where x.ItemId == id select x).FirstOrDefault();
return result;
}
}
public void Add(Item i)
{
using (var context = new ItemContext())
{
context.Set<Item>().Add(i);
context.SaveChanges();
}
}
}
以下代码创建一个新项,将其添加到存储库中,添加一些新的子项,然后保存更改。IItemRespository repo = new Repository();
//Create a new Item
Item parent = new Item() { Name = "Parent" };
repo.Add(parent);
//A long period of time may pass .. . .
//later add sub items
parent.SubItems.Add(new SubItem() { Name = "Child 1" });
parent.SubItems.Add(new SubItem() { Name = "Child 2" });
parent.SubItems.Add(new SubItem() { Name = "Child 3" });
//save the added sub items
repo.Save(parent);
当Save()方法尝试将该项附加到上下文时,我遇到了以下异常:
引用完整性约束冲突发生:定义参考约束的属性值在关系中的主体和从属对象之间不一致。
我意识到在存储库中的每个方法中都为其创建了一个新的上下文。这是故意的。添加项目和稍后编辑之间可能会有很长一段时间,我不想为整个时间保持上下文或数据库连接打开。
现在,如果我在添加子项之前将newItem附加到第二个上下文中,如下所示的代码,则可以正常工作。
//Create a new item
Item newItem = new Item() { Name = "Parent" };
using (ItemContext context1 = new ItemContext())
{
//Create a new aggrgate
context1.Set<Item>().Add(newItem);
context1.SaveChanges();
}
//Long period of time may pass
using (ItemContext context2 = new ItemContext())
{
context2.Set<Item>().Attach(newItem);
newItem.Name = "Edited Name";
newItem.SubItems.Add(new SubItem() { Name = "Child 1" });
newItem.SubItems.Add(new SubItem() { Name = "Child 2" });
newItem.SubItems.Add(new SubItem() { Name = "Child 3" });
context2.SaveChanges();
}
然而,如果我想真正遵循存储库模式,那么编辑Item的代码不应该知道存储库如何工作或ItemContext类的任何信息。它应该只能够对聚合根实体进行更改,然后通过存储库的Save()方法保存这些更改。
那么,我该如何修改我的Save()方法,以便正确保存对Item.SubItems的更改?