none
EF5 - DbContext.SaveChanges - datagrid saves updates but no inserts and deletes

    Question

  • Hi, can anyone help me with the following problem.

    The code has been generated by EF5 "Update model from database" wizard. tblModel has mapped stored procedures for updates, inserts and deletes.  But when executing the SaveChanges method only the update sp is being called (checked in SQL- Server Profiler), not the insert sp (however inserted rows are present in the datagrid). Can anyone explain what I'm missing?

    Code:
    private static CollectionManagerEntities context;
    private CollectionView LandCollectionView;

    public MainWindow()
    {
       InitializeComponent();

       context = new CollectionManagerEntities();
       LandCollectionView = (CollectionView)CollectionViewSource.GetDefaultView(context.tblLand.ToList());
      
       //Datagrid binding
       Binding myBinding_Landen = new Binding();
       myBinding_Landen.Source = LandCollectionView;
       dgLand.SetBinding(DataGrid.ItemsSourceProperty, myBinding_Landen);
    }

    private void btnSave_Click(object sender, RoutedEventArgs e)
    {
       context.SaveChanges(); //Only the update works, no inserts???
    }

    Kind regards,
    Coen

    Saturday, January 26, 2013 1:53 PM

Answers

  • Hi Alexander,

    It is pretty hard to find a good example of wpf EF4 or EF5 project in relationship with a datagrid and using mapped SQL-stored procedures (including an identity column). But I think I have setup a solution that works. Your explanation is correct. Inserted and deleted rows in the datagrid are not automatically put through to the context.

    What I did to get it working.
    a) Declare an ObservableCollection object, and set this to the ItemsSource property of the datagrid.
    b) Define a CollectionChanged event of the ObservableCollection object, to track the changes (inserts and deletes) of the datagrid and to get them updated in the context.

    The CollectionChanged event looks like:

    void Landen_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            foreach (tblLand myLand in e.NewItems)
            {
                context.tblLand.Add(myLand);
            }               
        }
        else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
        {
            foreach (tblLand myLand in e.OldItems)
            {
                context.tblLand.Remove(myLand);
            }   
        }
    }

    If anabody know a good example of WPF with DataGrid, EF, mapped SQL Stored Procedures, and the use of identity columns, please let me know.
    Regards, Coen

    • Proposed as answer by Alexander Sun Thursday, January 31, 2013 9:16 AM
    • Marked as answer by Coen Busker Thursday, January 31, 2013 10:28 AM
    Wednesday, January 30, 2013 9:50 AM

All replies

  • Hi Coen,

    Welcome to the MSDN forum.

    Please check if you add the new objects (inserted rows in the datagrid) into context. I mean it is tracked by context in this way:

    Context. tblLand.Add(newObject);

    Have a nice day.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Proposed as answer by Alexander Sun Thursday, January 31, 2013 9:16 AM
    Monday, January 28, 2013 5:25 AM
  • Hi Alexander, thank you for answering.

    You are right! When I explicitly add a new object (of type tblLand) it does work!! Then the (mapped) "insert stored procedure" is being called. What I don't understand:

    a) appearently, updates in the datagrid control are updated to the context, but new inserted or deleted rows are not?
    b) what is a good way of tracking the inserts and deletes of the datagrid control to have them get automatically into the context?

    Regards, Coen

    Monday, January 28, 2013 7:41 AM
  • Hi Coen,

    The new entity objects is not tracked by context, and datagrid do not add them automatically. Thus, you are required to add them manually. For deleted rows, if you mean you delete them from datagrid, I am not sure if you delete them from context or not. Datagrid do not delete them from context automatically, so you are required to do manually. In my humble opinion, I think you could bind add or delete action into corresponding event of datagrid to add to context or delete from context automatically.

    Have a nice day.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, January 29, 2013 9:05 AM
  • Hi Alexander,

    It is pretty hard to find a good example of wpf EF4 or EF5 project in relationship with a datagrid and using mapped SQL-stored procedures (including an identity column). But I think I have setup a solution that works. Your explanation is correct. Inserted and deleted rows in the datagrid are not automatically put through to the context.

    What I did to get it working.
    a) Declare an ObservableCollection object, and set this to the ItemsSource property of the datagrid.
    b) Define a CollectionChanged event of the ObservableCollection object, to track the changes (inserts and deletes) of the datagrid and to get them updated in the context.

    The CollectionChanged event looks like:

    void Landen_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            foreach (tblLand myLand in e.NewItems)
            {
                context.tblLand.Add(myLand);
            }               
        }
        else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
        {
            foreach (tblLand myLand in e.OldItems)
            {
                context.tblLand.Remove(myLand);
            }   
        }
    }

    If anabody know a good example of WPF with DataGrid, EF, mapped SQL Stored Procedures, and the use of identity columns, please let me know.
    Regards, Coen

    • Proposed as answer by Alexander Sun Thursday, January 31, 2013 9:16 AM
    • Marked as answer by Coen Busker Thursday, January 31, 2013 10:28 AM
    Wednesday, January 30, 2013 9:50 AM
  • Alexander,

    I'm trying to think of how to apply your solution to my WPF/MVVM program (with EF5) that is having the same problem. Here are the relevant code fragments...

    // members in my ViewModel...
    public CollectionViewSource MyEntitys { get; set; }
    private ObservableCollection<MyEntity> MyEntitysInternal { get; set; }

    // in my ViewModel constructor...
    MyEntitysInternal = repository.MyEntitys().Local;
    MyEntitys = new CollectionViewSource();
    MyEntitys.Source = this.MyEntitysInternal;

    // XAML
    <DataGrid x:Name="MyEntityDataGrid"
       AutoGenerateColumns="False" 
       CanUserAddRows="True"
        CanUserDeleteRows="True"
        IsReadOnly="False"
        SelectionMode="Single"
        SelectionUnit="FullRow"
        ItemsSource="{Binding MyEntitys.View, UpdateSourceTrigger=PropertyChanged}"
        SelectedItem="{Binding Path=CurrentMyEntity, Converter={StaticResource ignoreNewItemPlaceHolderConverter}}"
     IsSynchronizedWithCurrentItem="True">

    When I add a new row in the datagrid, I see in the ObservableCollection as type "System.Data.DynamicProxies.MyEntity_xxx", but SaveChanges doesn't write it to SQL.

    IgnoreNewItemPlaceholderConverter comes from here:  http://blog.spencen.com/2009/04/30/problems-binding-to-selectedvalue-with-microsoftrsquos-wpf-datagrid.aspx

    My questions are:

    1. With MVVM, it's necessary to create a CollectionViewSource (or lookup one declared in the XAML Resources), so how then should I set the ItemSource property of the datagrid?

    2. Where do you wire up the trigger to your _CollectionChanged event?

    Thanks!

    Monday, August 05, 2013 4:54 AM