none
Deleting child entity

    Question

  • Hi,

    I've a simple master-detail configuration.
    The master entity "Order" has a navigation property "OrderDetail".
    Using DbContext (EF 4.1, database first) I get the data this way:

    entities.Order.Load();
    ObservableCollection<Order> Orders = entities.Order.Local;

    Then I bind a datagrid to the Orders property above, and a child datagrid to Orders.OrderDetail.
    So far so good, I can insert and update records in both datagrids, and have the database updated when I call entities.SaveChanges.

    When I delete a row from OrdersDetail datagrid, the row actually disappear from the grid, but when I call SaveChanges I get the following 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

    This is a know behaviour. EF remove the relation, leaving the child entity orphan, instead of deleting it. 
    In this example EF try to set OrderDetail.OrderID = null, but find a not null constraint and give error.
    (To me this is the wrong behaviour. The default should be "delete", especially in situations like this where it is the only viable option.)

    Beth Massi blogged a workaround here, but it is for ObjectContext.

    Any way to fix it with DbContext?

    Regards,
     
    Corrado

    Tuesday, November 29, 2011 9:11 PM

Answers

  • Hi Corrado,

    You should call Remove method on DbSet<OrderDetail> collection. You can refer this link: http://blogs.msdn.com/b/adonet/archive/2011/03/08/ef-feature-ctp5-code-first-model-with-master-detail-wpf-application.aspx

      private void buttonSave_Click(object sender, RoutedEventArgs e)
     
        {
       // When you delete an object from the related entities collection (in our case Products),
            // The Entity Framework doesn’t mark these child entities as deleted.
            // Instead, it removes the relationship between the parent and the child 
            // by setting the parent reference to null. 
            // So we manually have to delete the products that have a Category reference set to null.
            // The following code uses LINQ to Objects against the Local collection of Products.
     
            // The ToList call is required because otherwise the collection will be modified 
    
            // by the Remove call while it is being enumerated. 
    
            // In most other situations you can do LINQ to Objects directly against the Local property without using ToList first.
    
            foreach (var product in _context.Products.Local.ToList())
            {
                if (product.Category == null)
                {
                    _context.Products.Remove(product);
                }
            }
            _context.SaveChanges();
            // Refresh the grids so the database generated values show up.
    
            this.categoryDataGrid.Items.Refresh();
            this.productsDataGrid.Items.Refresh();
        }
    
    

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by corradolab Thursday, December 1, 2011 7:49 AM
    Thursday, December 1, 2011 6:40 AM
    Moderator

All replies

  • Hi Corrado,

    You should call Remove method on DbSet<OrderDetail> collection. You can refer this link: http://blogs.msdn.com/b/adonet/archive/2011/03/08/ef-feature-ctp5-code-first-model-with-master-detail-wpf-application.aspx

      private void buttonSave_Click(object sender, RoutedEventArgs e)
     
        {
       // When you delete an object from the related entities collection (in our case Products),
            // The Entity Framework doesn’t mark these child entities as deleted.
            // Instead, it removes the relationship between the parent and the child 
            // by setting the parent reference to null. 
            // So we manually have to delete the products that have a Category reference set to null.
            // The following code uses LINQ to Objects against the Local collection of Products.
     
            // The ToList call is required because otherwise the collection will be modified 
    
            // by the Remove call while it is being enumerated. 
    
            // In most other situations you can do LINQ to Objects directly against the Local property without using ToList first.
    
            foreach (var product in _context.Products.Local.ToList())
            {
                if (product.Category == null)
                {
                    _context.Products.Remove(product);
                }
            }
            _context.SaveChanges();
            // Refresh the grids so the database generated values show up.
    
            this.categoryDataGrid.Items.Refresh();
            this.productsDataGrid.Items.Refresh();
        }
    
    

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by corradolab Thursday, December 1, 2011 7:49 AM
    Thursday, December 1, 2011 6:40 AM
    Moderator
  • Hi Alan,

    I've just found the same article and going to answer myself, but you was faster :)

    Thank you for your help.

    BTW, the method suggested here is much simpler then the one showed by Beth.

    Regards,
      Corrado

     

    Thursday, December 1, 2011 7:49 AM
  • Hi Corrado,

    You're welcome, I'm glad to help.

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, December 1, 2011 8:12 AM
    Moderator