0

(I've checked the related questions, and can't find an answer.)

I'm doing some tests with Code First Entity Framework 6. I have a "Child" entity that references two "Parent" entities.

I want to create the child entity and parent entities, and then save them all at once (so I can cut down on the number of db.Save() calls, and to keep it as one unit of work).

public class Child
{
    public int ChildID { get; set; }
    public string Name { get; set; }

    public virtual Parent Father { get; set; }
    public virtual Parent Mother { get; set; }
}

public class Parent
{
    public int ParentID { get; set; }
    public string Name { get; set; }

    [ForeignKey("Child")]
    public int? ChildID { get; set; }
    public virtual Child Child { get; set; }
}

(A bit of a confusing setup -- the parents are actually the "children" of the child in the relationship. I know it's bad abstraction. This is just a test.)

Controller:

    public ActionResult AddWithParents()
    {
        Parent father = new Parent { Name = "Test Father" };
        Parent mother = new Parent { Name = "Test Mother" };

        Child newChild = new Child
        {
            Name = "Test Child",
            Father = father,
            Mother = mother
        };


        db.Children.Add(newChild);

        father.Child = newChild;
        mother.Child = newChild;

        db.SaveChanges();            

        return RedirectToAction("Index");
    }

This works, but doesn't populate the Parent.ChildID foreign key.

If I do something like father.Child = newChild, I get the following error:

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details. Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

Is there any way to get this to work?

Masoud
  • 8,020
  • 12
  • 62
  • 123
mcfroob
  • 1,044
  • 1
  • 11
  • 13
  • What's your inner exception? If it shows `SqlException`, check your datetime data type against null or out-of-range values if exist. – Tetsuya Yamamoto Dec 07 '16 at 06:07
  • There is no datatime in the models. Somebody reformatted my question so the inner exception is part of the main exception, but the inner exception is: Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values. – mcfroob Dec 07 '16 at 07:18
  • Well, your inner exception tells me that you've circular dependency problem where EF tries to find an entity that has null or invalid primary key value. Check if a foreign key has nullable type or examine relationship between related tables. Then, what type of relationship you want to make (1:1, 1:n)? – Tetsuya Yamamoto Dec 07 '16 at 07:25

1 Answers1

1

I figured out problem source in your code: the ChildId property in Parent class declared as nullable integer type, while ChildId property in Child class belongs to non-nullable integer type, which they're different types (Nullable<int> against int).

Hence, you should declare ChildId property in Parent class as non-nullable type, thus circular reference problem should be solved as this:

public class Child
{
    public int ChildID { get; set; }
    public string Name { get; set; }

    public virtual Parent Father { get; set; }
    public virtual Parent Mother { get; set; }
}

public class Parent
{
    public int ParentID { get; set; }
    public string Name { get; set; }

    [ForeignKey("Child")]
    public int ChildID { get; set; } // set this FK as non-nullable int
    public virtual Child Child { get; set; }
}

According to this answer, circular dependency problem occurs when a foreign key property data type mismatch with source primary key, or a foreign key property has been set incorrectly.

Edit: Since ChildId property in Child class is non-nullable int primary key property in database table, the best way to remove circular dependency is setting foreign key with same data type as primary key (i.e. int).

Related problem:

Clean way to deal with circular references in EF?

Unable to determine a valid ordering for dependent operations

Community
  • 1
  • 1
Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
  • The foreign key is nullable. Making the ChildID nullable will compile, but if you look at the database after the migration, ChildID still won't allow nulls since it's a primary key. So the Parent objects will still have a null ID for their parent (child) objects. Thanks for your effort though. I agree it is probably best to remove the circular reference. – mcfroob Dec 07 '16 at 08:26
  • Well, I missed the point where `ChildId` in `Child` class is a primary key property. I edited the solution with setting FK `ChildId` field in `Parent` class as non-nullable `int` type, thus it matches `Child` table primary key definition. – Tetsuya Yamamoto Dec 07 '16 at 08:37