Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用实体框架向集合添加项_C#_.net_Entity Framework 4_Domain Driven Design_Ddd Repositories - Fatal编程技术网

C# 使用实体框架向集合添加项

C# 使用实体框架向集合添加项,c#,.net,entity-framework-4,domain-driven-design,ddd-repositories,C#,.net,Entity Framework 4,Domain Driven Design,Ddd Repositories,我尝试使用EntityFramework4遵循DDD存储库模式。但保存对聚合根集合属性的更改时遇到问题。考虑下面的课。Item是包含子项实体集合的聚合根 public class Item { public int ItemId { get; set; } public string Name { get; set; } public ICollection<SubItem> SubItems { get; private set; } public

我尝试使用EntityFramework4遵循DDD存储库模式。但保存对聚合根集合属性的更改时遇到问题。考虑下面的课。Item是包含子项实体集合的聚合根

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; }
}
现在,这里是设置EF映射的DbContext类

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);
    }
}
当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 newItem=newItem(){Name=“Parent”};
使用(itemcontext1=newitemcontext())
{
//创建一个新的聚合
context1.Set().Add(newItem);
context1.SaveChanges();
}
//很长一段时间可能会过去
使用(itemcontext2=newitemcontext())
{
context2.Set().Attach(newItem);
newItem.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();
}
然而,如果我想对存储库模式保持真实,那么编辑项的代码就不应该知道存储库或ItemContext类的工作方式。它应该能够对聚合根实体进行更改,然后通过repository 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();
        }
    }
公共作废保存(项目一)
{
使用(var context=new ItemContext())
{
foreach(i.子项中的var子项)
{
if(subitem.SubItemId==0)
context.Set().Add(子项);
其他的
context.Set().Attach(子项);
}
context.Set().Attach(i);
SaveChanges();
}
}
原因是,因为在执行附加时实体未附加到上下文,EF实际上不知道实体来自何处-它认为未设置的FK(可能为0)是有效状态-这就是错误的来源。需要首先附加子对象的原因是,您可以实际添加而不是附加。同样,由于附加子项时您的上下文不活动,EF不确定实体来自何处,并假设0 PK是正确的,从而导致错误。

模型

public virtual ICollection<CostCenter> CostCenters { get; set; }

[NotMapped]
public int CostCenterId { get; set; }//Just to get item in view
创建帖子

public ActionResult Create(Campaign campaign)
{
    ...
    campaign.CostCenters.Add(db.CostCenters.FirstOrDefault(f => f.Id == campaign.CostCenterId);
    return RedirectToAction("Index");
}
看法

model.CostCenterId)%%>
model.CostCenterId)%%>

这并不能解释什么该死的事情
    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();
        }
    }
public virtual ICollection<CostCenter> CostCenters { get; set; }

[NotMapped]
public int CostCenterId { get; set; }//Just to get item in view
public ActionResult Create()
{
    ViewBag.CostCenterId = new SelectList(db.CostCenters, "Id", "Name");
    return View();
}
public ActionResult Create(Campaign campaign)
{
    ...
    campaign.CostCenters.Add(db.CostCenters.FirstOrDefault(f => f.Id == campaign.CostCenterId);
    return RedirectToAction("Index");
}
<%: Html.LabelFor(model => model.CostCenterId ) %>
<div class="input-control">
    <%: Html.DropDownList("CostCenterId ", String.Empty) %>
    <%: Html.ValidationMessageFor(model => model.CostCenterId ) %>
</div>