在EF C#中使用依赖于代码的实体

时间:2013-01-23 11:48:43

标签: c# sql entity-framework dependency-management

我必须使用实体AB

A有字段: id(PK)和b_fk(FK到B's id)。 B有类似的字段: id(PK)和a_fk(FK到A's id)。

现在我要创建对象AB

createAAndBMethod(Entities context){
    A a = new A();
    B b = new B();
    a.b_fk = b;
    b.a_fk = a;
    context.As.AddObject(a);
    context.Bs.AddObject(b);
}

someImportantMethod(){
    //do sth
    Entities context = new Entities(...);
    //do sth, maybe some changes to db on context
    createAAndBMethod(context);
    //do sth, maybe some changes to db on context
    context.SaveChanges();// <-- here I'm getting error
}

保存不适用于错误:Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

有没有办法让这个保存一次? 我需要在某些代码中创建两个不应保存更改的对象,因此我无法在任何地方执行context.SaveChanges()

context.SaveChanges()上可能发生类似:

 Create newA with nulled field b_fk
 Create newB with a_fk = newA
 Set newA.b_fk to newB

更新: a_fkb_fk都可以为空。我正在使用MS SQL和Azure SQL。

UPDATE2: 我将createAAndBMethod(Entities context)更改为:

createAAndBMethod(Entities context){
    A a = new A();
    context.As.AddObject(a);
    B b = new B();
    a.b_fk = b;
}

但它仍然无法解决相同的错误。

3 个答案:

答案 0 :(得分:1)

尝试删除这些行:

b.a_fk = a;

context.Bs.AddObject(b);

我认为您将对象b添加到上下文两次。当您使用外键添加对象a时,EF会自动执行此操作。

<强>更新

尝试以下两种变体:

  createAAndBMethod1(Entities context)
  {
        A a = new A();
        B b = new B();
        a.b_fk = b;
        b.a_fk = a;
        context.As.AddObject(a);
  } 

createAAndBMethod2(Entities context)
{
        A a = new A();
        B b = new B();
        a.b_fk = b;
        context.As.AddObject(a);
        context.SaveChanges();
        b.a_fk = a;
        context.SaveChanges();    
}

答案 1 :(得分:1)

我认为你的模特有问题;表有一个B表的外键引用;和B表有一个A表的外键引用。那么为什么不合并这些表只创建一个表?

如果你想创建一对一的关系,这不是正确的方法。

更新: 数据库设计不合适。只在表B中创建外键就足够了。表A中没有必要创建外键,因为这样的设计满足“A可能有0或多个B”。

答案 2 :(得分:0)

你想要使用一个上下文,同时你有两个表。

    var p = new Person()
    {
        LastName = "test1111111111",
    };
    var c = new Child()
    {
        Name = "Testchild"
    };
    PersonTest(p, c);

    public void PersonTest(Person ob, Child ob2)
    {
        try
        {
            using (var con = new Entities())
            {
                con.Configuration.AutoDetectChangesEnabled = false;
                var o = new Person();
                if (ob.PersonId > 0)
                    o = con.People.Find(ob.PersonId);

                o.PersonId = ob.PersonId;
                o.LastName = ob.LastName;
                if (ob.PersonId == 0)
                    con.People.Add(o);
                con.ChangeTracker.DetectChanges();
                con.SaveChanges();
                i = o.PersonId;

                var o2 = new Child();
                if (ob2.ChildrenId > 0)
                    o2 = con.Children.Find(ob.PersonId);

                o2.PersonId = ob2.ChildrenId;
                o2.Name = ob2.Name;
                o2.PersonId = i;
                if (ob2.ChildrenId == 0)
                    con.Children.Add(o2);
                con.SaveChanges();
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.InnerException.Message);
        }
        finally
        {
            con.Configuration.AutoDetectChangesEnabled = true;
        }
    }