none
[EF 6.1.3] How to change the relationship between two enties, (change the parent) RRS feed

  • Question

  • I have two entities, Parents and Childs.

    When I get the parents from the database, I use the Include to include the childs. But soemtimes I need to change the parent of the childs, from one parent that exists in the database to a new parent does not exists in the database.

    I do the follwing:

    Parents myActualParent = dbContext.Parents.Where(x=> x.IDParent == 1)
    .Include(x=> x.Childs)
    .SingleOrDefault();
    
    Parents myNewParent = new Parents();
    MyNewParent.Childs.AddRange(myActualParent.Childs);
    myActualParent.Childs.Clear();
    
    foreach(Childs iteratorChild in myNewParent.Childs)
    {
        iteratorChild.IDParent = myNewParent.IDParent;
        iteratorChild.Parent = myNewParent;
    }
    

    The IDParent and IDChild is a bigint autonumeric, and the column Childs.IDParent does not allow null values.

    When I save the changes, I get this error:

    "The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted."

    The message seems clear, if I am not wrong, I have two solutions:

    1.- allow null values in the colum Child.IDParent in the database. But I don't like this solution so much, because it would be desing the database thinking of EF, and I want to design the database without thiking in the way that I access to the database and the limitations of EF.

    2.- The second solution is set the FK to a non null value. In this case I am setting 0 as value, but it does not work.

    If I do the same, but with two parents that exist in the database, then I don't have problems, the problem happens when the new parent is a new parent that does not exist in the database.

    I would like to know which is the way to change the parent in this case.

    Thank you so much.

    Saturday, April 9, 2016 4:37 PM

Answers

  • Your solution works, so I am wondering why when the parent is new and the child is new it works and when the parent is new and the child is not new, I get the error. I guess that it should work in both cases.

    That's because the DB engine sees everything new, and it is going to assign the primary-key of an auto incremented id to the to the parent record. Then  child is saved within the save sequence and assign the parent ID to the child record's foreign-key and the child gets its record id. EF steps in and populates this information back to the entities. The Entities can be address after save of the objects by EF and address the objects keys while the objects are still in memory.

    But  I would like to keep the ID of the child, because if I create a new one, I get a new ID, and I would like to keep the ID of the child to know that is this child who is changed and no other, that perhaps has the same information. So I would have two childs, with the same information but with different IDs.

    That would be an insert of a parent and trying to attach children is some kind of update sequence. It looks kind of questionable. I don't know. You'll have to figure it, if it is even possible. To find out, you should first try this with T-SQL in the MS SQL Server Management Studio. If successful there, then you can make EF execute the T-SQL in an Sproc at best.

     

    Sunday, April 10, 2016 12:41 PM

All replies

  • Why wouldn't you just make the parent, copy the children by making a new child object, copy the data out of the old child to new child, add new child  the new parent's child collection and just do a save on the parent?

    EF would make the relationship between the parent and children by itself.

    Saturday, April 9, 2016 8:50 PM
  • Thanks for your suggestion. I have tried this code to test:

    Parents myNewParent = new Parent();
    Childs myChild = new Childs();       
    
    dbContext.Parents.Local.Add(myParent);
    
    myParent.Add(myChild);
    myChild.Parents = myParent;
    
    await dbContext.SaveChangesAsync();

    This code reproduce your suggestion, I have a new parent, I create a new child that I add to the parent and I can copy the information of the old child to this new child.

    Your solution works, so I am wondering why when the parent is new and the child is new it works and when the parent is new and the child is not new, I get the error. I guess that it should work in both cases.

    But  I would like to keep the ID of the child, because if I create a new one, I get a new ID, and I would like to keep the ID of the child to know that is this child who is changed and no other, that perhaps has the same information. So I would have two childs, with the same information but with different IDs.

    Thanks for your suggestion.




    Sunday, April 10, 2016 10:23 AM
  • Your solution works, so I am wondering why when the parent is new and the child is new it works and when the parent is new and the child is not new, I get the error. I guess that it should work in both cases.

    That's because the DB engine sees everything new, and it is going to assign the primary-key of an auto incremented id to the to the parent record. Then  child is saved within the save sequence and assign the parent ID to the child record's foreign-key and the child gets its record id. EF steps in and populates this information back to the entities. The Entities can be address after save of the objects by EF and address the objects keys while the objects are still in memory.

    But  I would like to keep the ID of the child, because if I create a new one, I get a new ID, and I would like to keep the ID of the child to know that is this child who is changed and no other, that perhaps has the same information. So I would have two childs, with the same information but with different IDs.

    That would be an insert of a parent and trying to attach children is some kind of update sequence. It looks kind of questionable. I don't know. You'll have to figure it, if it is even possible. To find out, you should first try this with T-SQL in the MS SQL Server Management Studio. If successful there, then you can make EF execute the T-SQL in an Sproc at best.

     

    Sunday, April 10, 2016 12:41 PM