none
Remove() method in ViewModel results in Entity state of modified and not delete RRS feed

  • Question

  • I am using the EF Code First approach and have a parent entity that has 1 to many child entities set up in a master/detail style format. In my view, I have attached one of the child entity lists to a datagrid and added a delete button for each row. In my view model I attached a delete command to those buttons. The code in the view model finds the correct object to delete by ID and then uses the Remove() method to delete it. But when I look in dbContext I see that the entity is in a state of modified and not delete. Am I using the incorrect process for removing entities in the DbContext? I'm wondering if instead I should have a custom Delete() in my DbContext that is called from my Repository which can then be used by the view model.

        Public Sub DeleteClientMappingRecord(ByVal id As Integer)
            Dim obj As ClientMapping = _mappingrecord.Clients.Single(Function(x) x.ClientMappingID = id)
            Dim info As Client = _clientlist.Single(Function(x) x.ClientID = obj.ClientID)
            _mappingrecord.Clients.Remove(obj)
            OnPropertyChanged("UserMappingRecord")
        End Sub
    
    

     

    Saturday, November 12, 2011 7:38 PM

Answers

  • Hi pretzelb,

    Thanks for your feedback.

    To tell your truth, I'm not good at WPF, But for delete the children entities, we should remove them from the their own DbSet. If your database allows null for foreign key, you Call the Remove method on the parent navigation but it just to modify the foriegn key to null-- so the state is modified.

    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.

    Tuesday, November 15, 2011 8:32 AM
    Moderator

All replies

  • Hi pretzelb,

    Welcome!

    ----------------

    Marks the given entity as Deleted. When the changes are saved, the entity is deleted from the database. The entity must exist in the context in some other state before this method is called. (http://msdn.microsoft.com/en-us/library/system.data.entity.dbset.remove(v=vs.103).aspx)

    ----------------

    I think Remove method is right here,  Singe method will find the record in database. I think you can test to use Find method: http://msdn.microsoft.com/en-us/library/gg696418(v=vs.103).aspx

    BTW, Are the records deleted when the SaveChange() method is called.

    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.

    Monday, November 14, 2011 7:21 AM
    Moderator
  • The Remove() you are linked to is the method under DbSet. What I was doing was calling Remove() in my view model on the ObservableCollection.

        Public Property Clients() As ObservableCollection(Of ClientMapping)
    
    

    When I call remove in the view model it wipes out the primary key that links the child entity to it's parent, which I believe is the correct behavior for a delete. But as I said, the entity is marked as modified and not deleted which I think is incorrect. I'm not sure if this is a bug or not.

    But it would seem that my view model needs to call a method that uses the Remove() on the DbSet. For that I will need to create something and make it public probably via my Repository. Unless someone disagrees.

    I think I should also point out the parent/child relationship of the entity because it might be the root of the problem. Here is a sample of the entity:

    Public Class EmpDetailMaster
        Public Property EmpID() As String
        Public Property ProductLines() As ObservableCollection(Of ProductLineMapping)
        Public Property Clients() As ObservableCollection(Of ClientMapping)
    End Class

    The intent was to create a view which was bound to a view model containing an instance of the EmpDetailMaster for a selected employee. Logically it made sense to me. In the case of my original question, a DataGrid is bound to the Clients() property.

    In the view model, I can invoke a Remove() on the EmpDetail.Clients but as I said it's being marked as updated. I just did some research trying to invoke Remove() on the DbSet but in my DbContext I've defined it as the parent level so it's at the EmpDetailMaster level. There is not DbSet for the ClientMapping list. I cannot invoke EmpDetailMaster.Remove() to try and delete a child of type ClientMapping.

    I now question whether or not my idea of a logical entity mapping was wise. The parent/child creation I have makes logical sense but it appears to overly complicate simple CRUD tasks because the child entities do not have their own DbSet.

    • Edited by pretzelb Monday, November 14, 2011 3:51 PM add details on parent/child
    Monday, November 14, 2011 2:49 PM
  • Hi pretzelb,

    Thanks for your feedback.

    To tell your truth, I'm not good at WPF, But for delete the children entities, we should remove them from the their own DbSet. If your database allows null for foreign key, you Call the Remove method on the parent navigation but it just to modify the foriegn key to null-- so the state is modified.

    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.

    Tuesday, November 15, 2011 8:32 AM
    Moderator
  • If the correct process is to invoke the Remove() on the child Entity via DbSet then my DbContext would change dramatically from a logical point of view. Instead of just having a single DbSet for the parent entity I would instead have to have something like this: 

    Public Property EmpParentList As DbSet(Of EmpDetailMaster)
    Public Property ClientChildList As DbSet(Of ClientMapping)
    Public Property ProductLineChildList As DbSet(Of ProductLineMapping)
    
    

    If I'm forced to do something like this so I can directly call Remove() on a child entity then why bother even creating the logical parent model?

    Having the child entity in a modified state with null for the foreign key makes it difficult to distinguish from truely modified entities.

    Tuesday, November 15, 2011 3:21 PM
  • Hi,

    Remove the children item from Children Dbset is right way:

    -----------------------------------------------

     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.

    Friday, November 18, 2011 9:05 AM
    Moderator