locked
EF throws exception if related ICollection items are Removed RRS feed

  • Question

  • Hi,

    I am fighting with this problem for a two days. (I am using EF 6.0) 

    Here is situation:

    I have two tables

    Table:1: Id-Table1,Prop1,Prop2,Prop3,Prop4 etc

    Table:2: Id-Table2, FK-Table1 (of table1) Prop1,Prop2,Prop3,Prop4 etc

    Mapping:

    X -> ---(ICollection prop of table 2 objects )---

    this -> Parent (table1) object

      this.HasMany(o => o.X).WithRequired()
                    .HasForeignKey(fk => fk. FK-Table1).WillCascadeOnDelete(true);

    This runs well, mapping works fine. In parent object ICollection is loaded with items.

    All Id's in tables are non-nullable.

    Now if i Do

    ICollection.Clear(), And do saveChanges on dataContext i geT:

    Additional information: 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.

    Can someone help me with this one?

    Thanks.

    Updated:

    If I explicit set entity state  -> Deleted
    Item from ICollection is removed and I am able to save changes without errors....

    • Edited by Valdis1987 Wednesday, June 18, 2014 7:20 AM
    Wednesday, June 18, 2014 6:50 AM

Answers

  • Hello,

    >> But it's kind a strange implementation. Why EF don't delete records from db, but just removes FK?

    This is because the Clear() method removes the reference to the entity, not the entity itself.

    >> I there a specific mapping behavior to tell EF to delete record from db if item is deleted from Collection?

    You can have a try this solution from syned as:

    public class Sample20140618Context : DbContext
    
        {
    
            public DbSet<Parent> Parents { get; set; }
    
    
            public DbSet<Child> Childs { get; set; }
    
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
            {
    
                modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });
    
                modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId);
    
            }
    
        }
    
    
        public class Parent
    
        {
    
            public int ParentId { get; set; }
    
            public ICollection<Child> Children { get; set; }
    
        }
    
    
        public class Child
    
        {
    
            public int ChildId { get; set; }
    
            public int ParentId { get; set; }
    
        }
    

    Then when calling the Clear() method, it would delete the sub records as well.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Valdis1987 Thursday, June 19, 2014 9:21 AM
    Thursday, June 19, 2014 4:20 AM

All replies

  • Hello,

    >>If I explicit set entity state  -> Deleted Item from ICollection is removed and I am able to save changes without errors....

    This is because the results of two behavior are different. The “ICollection.Clear()” is to clean the foreign key relationships between two tables, it will try to set the foreign key to be null without deleting the record however in your case it is non-nullable so that it throws that error. While explicit setting entity state to be deleted, it will delete these sub records in database as well if your code statement is like below:

    using (DFDBEntities db = new DFDBEntities())
    
                    {
    
                        //var result = db.ProGetOrder();
    
    
                        var result = db.Orders.FirstOrDefault();
    
    
                        foreach (OrderDetail od in result.OrderDetails.ToList())
    
                        {
    
                            db.Entry<OrderDetail>(od).State = EntityState.Deleted;
    
                        }
    
    
                        db.SaveChanges();
    
                    }
    

    If I misunderstand, please let me know.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, June 18, 2014 10:06 AM
  • Hi, 

    Yes that is the same logic that i now using.

    But it's kind a strange implementation. Why EF don't delete records from db, but just removes FK?

    I there a specific mapping behavior to tell EF to delete record from db if item is deleted from Collection?

    If i remember correctly Nhibernate have that logic, if item is deleted from list, related record is deleted from DB.

    Thanks,

    Wednesday, June 18, 2014 10:20 AM
  • Hello,

    >> But it's kind a strange implementation. Why EF don't delete records from db, but just removes FK?

    This is because the Clear() method removes the reference to the entity, not the entity itself.

    >> I there a specific mapping behavior to tell EF to delete record from db if item is deleted from Collection?

    You can have a try this solution from syned as:

    public class Sample20140618Context : DbContext
    
        {
    
            public DbSet<Parent> Parents { get; set; }
    
    
            public DbSet<Child> Childs { get; set; }
    
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
            {
    
                modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });
    
                modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId);
    
            }
    
        }
    
    
        public class Parent
    
        {
    
            public int ParentId { get; set; }
    
            public ICollection<Child> Children { get; set; }
    
        }
    
    
        public class Child
    
        {
    
            public int ChildId { get; set; }
    
            public int ParentId { get; set; }
    
        }
    

    Then when calling the Clear() method, it would delete the sub records as well.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Valdis1987 Thursday, June 19, 2014 9:21 AM
    Thursday, June 19, 2014 4:20 AM
  • JEEEEEe

    This one:

      modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });

    Is that magic..............

    I have no idea, why!!!!

    Can you give small explanation?!

    Mega thanks.

    Thursday, June 19, 2014 9:24 AM
  • Hi,

    I think it is explained by syned:

    It creates Identifying relationship between parent and child entities.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, June 20, 2014 8:56 AM