gpt4 book ai didi

c# - 使用 Entity Framework 将项目添加到集合

转载 作者:可可西里 更新时间:2023-11-01 08:24:32 25 4
gpt4 key购买 nike

我正在尝试使用 Entity Framework 4 遵循 DDD 存储库模式。但是我在保存对聚合根的集合属性的更改时遇到了问题。考虑我下面的类(class)。 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; }
}

接下来我为聚合根类定义了一个存储库接口(interface)

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() 方法尝试将项目附加到上下文时,出现以下异常。

A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.

我意识到我正在为存储库中的每个方法创建一个新的上下文。这是故意的。添加项目和稍后编辑项目之间可能会经过很长一段时间,我不想在整个时间内保持上下文或数据库连接打开。

现在,如果我在添加子项目之前将 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 的更改?

最佳答案

您需要通过设置一些属性来帮助 EF 使其正常工作。

当你创建一个新的子项时,你需要自己设置 FK:

   parent.SubItems.Add(new SubItem() { Name = "Child 1", ItemId = parent.ItemId});
parent.SubItems.Add(new SubItem() { Name = "Child 2", ItemId = parent.ItemId });
parent.SubItems.Add(new SubItem() { Name = "Child 3", ItemId = parent.ItemId });

然后在您的保存功能中,将项目添加或附加到您的上下文中:

    public void Save(Item i)
{
using (var context = new ItemContext())
{
foreach (var subitem in i.SubItems)
{
if (subitem.SubItemId == 0)
context.Set<SubItem>().Add(subitem);
else
context.Set<SubItem>().Attach(subitem);
}
context.Set<Item>().Attach(i);
context.SaveChanges();
}
}

原因是,因为在执行附加时您的实体未附加到上下文,EF 实际上不知道实体来自何处 - 它认为未设置 FK(可能为 0)是有效状态 - 这是您的错误来源。您需要首先附加子对象的原因是您可以实际添加而不是附加。同样,由于附加子项时您的上下文不存在,因此 EF 不确定实体来自何处,并假定 0 PK 是正确的,从而造成您的错误。

关于c# - 使用 Entity Framework 将项目添加到集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13282610/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com