如何将相关对象添加到EF6中的上下文

时间:2015-08-19 22:05:12

标签: c# entity-framework

我有两个班级

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<B> { get; set; }
}

public class B
{
    public int Id { get; set; }
    public A A { get; set; }
    public string Name { get; set; }
}

ICollection可能为null所以首先我按以下方式创建和添加类型A的对象。首先,我有一个添加项目的通用方法:

public void Add<T>(T item)
{
    using ( var context = new DbContext())
    {
        context.Set<T>().Add(obj);
        context.SaveChanges();
    }
}

然后:

A objA = new A() { Name = "Object A" };
Add<A>(objA);

到目前为止一切正常。添加类型B的相关对象时出现问题。

B objB = new B() { Name = "Object B", A = objA }
Add<B>(objB);

添加objB导致重复objA(具有不同的Id)。我不确定我错在哪里。请帮忙。

提前致谢。

2 个答案:

答案 0 :(得分:1)

这就是为什么在DbContextDbSet周围使用这层包装器几乎没有任何帮助。

您的Add方法唯一可以做的就是,将 A实体添加到数据库,以及与其连接的任何实体(也称为对象图)。在其中使用的方法DbSet.Add将每个实体标记为Added,其(1)可从A实例到达,(2)尚未附加到上下文。好吧,你在方法中创建了上下文,因此在添加A之前,嵌套实体无法连接。

但这不是你唯一的问题。除非将所有A个调用都包含在Add中,否则您也无法在一个事务中向数据库添加更多实体(甚至不超过一个TransactionScope实体)。无法使用一个SaveChanges调用来提交一个完整的工作单元。

我不知道这个Add方法所在的位置,但您应该以某种方式重构代码,以便在保存更改之前有更多的自由来操作对象图。

没有任何包装器,这个任务就像这样完成:

using(var context = new MyContext())
{
    A objA = context.As.Find(id); // id is a variable holding an existing A's Id

    // Now objA is attached to the context and won't be added.
    B objB = new B() { Name = "Object B", A = objA };
    context.Bs.Add(objB);
    context.SaveChanges();
}

答案 1 :(得分:0)

我建议你在课程中使用外键属性:

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<B> { get; set; }
}

public class B
{
    public int Id { get; set; }
    public string Name { get; set; }

    [ForeignKey("A")]
    public int AId { get; set; }    
    public virtual A A { get; set; }
}

这样,您可以在创建B类型时设置引用键ID而不是整个对象。

B objB = new B() 
{ 
    Name = "Object B",
    AId = objA.Id // Set object ID here
};

Add<B>(objB);

希望它可以帮到你!