Need help with understanding DbUpdateConcurrencyException

I created a standard CRUD operation.

When I tested this it was fine as it related to DbUpdateConcurrencyException ie. if I brought up a record in the Edit Dialog but subsequently changed it outside of the App but then tried to update from the Edit Dialog, a DbUpdateConcurrencyException is raised and the Reload button is displayed as expected.

This is all fine except the Datagrid brings down a lot of info as the table has many fields and only a small number are displayed in the grid and there is also some complex filtering.

So what I did was use a stored procedure for the list displayed in the Datagrid.

Now I find when the above triggered DbUpdateConcurrencyException , this is no longer triggers and therefore an edit done outside of the App is overwritten and no DbUpdateConcurrencyException .

Trying to understand what I need to do on the Edit Form to fix that.

Thank you. Appreciate your help on this.

S

The DbUpdateConcurrencyException relies on entity tracking. When you use a stored procedure entities are not tracked. This is a feature of Entity Framework and we are not aware of any workaround for it.

Thank you Korchev.

I'm only using a stored procedsure for the datagrid. The Edit Form which is a separate page still uses the same code that was generated ie. entities.

So when I open the Edit Form, the data is retrieved and display (I presume from the database) and this should be the unchanged data. To test concurrency, I manually change a piece of the data displayed in the Edit Form via SQL and then on the Edit Form, change another peice of data and try and save. As DbUpdateConcurrencyException is not raised, the change manually made via SQL is overwrite and that was unchanged in the Edit Form.

Is there some connection between the Datagrid page and the Edit Form page because Edit Form still uses entities to retrieve the data and only the datgrid page has been changed to use stored procedure.

If I can understand what is going on, I might be able to do a workaround.

Thank you once again for your assistance.

If this is any help, here's the code in DbService that is run in the Update (from the Edit Form). This is unchanged using the original generated code and that when the datagrid was using a stored procedure.

    public async Task<Models.AgcPortalDb.Customer> UpdateCustomer(int? agcReference, Models.AgcPortalDb.Customer customer)
    {
        OnCustomerUpdated(customer);

        var itemToUpdate = Context.Customers
                          .Where(i => i.CustReference == custReference)
                          .FirstOrDefault();
        if (itemToUpdate == null)
        {
           throw new Exception("Item no longer available");
        }

        var entryToUpdate = Context.Entry(itemToUpdate);
        entryToUpdate.CurrentValues.SetValues(customer);
        entryToUpdate.State = EntityState.Modified;
        Context.SaveChanges();       

        OnAfterCustomerUpdated(customer);

        return customer;
    }

Additionally I noted that if I create another datagrid (using a duplicate of the datagrid bound to the SP) on the page and bind to GetCustomers (ie entities), meaning that there is one datagrid bound to the SP and another to the entities. If I now trigger a Edit Dialog from the datagrid bound to the SP, the Concurrency exception is generated.

The datagrid page and the edit dialog pages are different so don't understand why the edit dialog page doesn't trigger a Concurrency exception is there is only one datagrid bound to the SP but does trigger exception when I duplicate the datagrid which is bound to the entities. There must be some connection between the update in the edit dialog and the datagrid page. Don't quite understand how & how to go about creating a workaround.

Appreciate any assistance you can provide on this.

Yes, your observations are correct - in order to see the concurrency exception you need to use the entities. This is how Entity Framework implements entity tracking.

Yes - the connection is that both GetXXX and UpdateXXX methods use the entities. You can check the generated source.

As I said in my first reply - there is no workaround that we know of. If you want to rely on the DbUpdateConcurrencyException you have to use entities and not a stored procedure.