DataGrid cancel inline edits

Hi,

I'm using v2.62.3 of Radzen and noticed some oddities around inline edits / cancelling. I have a SQL Server 2016 back-end with a simple table which has a primary key which is an integer identity (named "ID") and a nvarchar field for a description.

I add the table to the data source in Radzen via infer and then create a new page using the "DataGrid InLine Edit" page wizard onto the table using the wizards default options (Allow paging, Allow sorting, allow filtering, use advanced datagrid filter) and all fields in the table displayed.

NOTE: not sure if this makes a difference but, the data source has had "Enable Entity Framework query tracking" unticked

I run the Radzen application and:

  • Open the new page
  • Click the inline edit button for the first record and change the description by adding a few characters and then press the inline edit cancel button
  • The description still shows the editted value from the cancelled edit rather than the actual value in the database
  • Navigate to another page and then back to the new page I created
  • The page re-opens now showing the actual values from the database
  • Click the inline edit for the first record and change the description again and press the inline edit cancel button

At this point, I get this exception:

dotnet: warn: Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer[100]
      Unhandled exception rendering component: The instance of entity type 'PnDemandPlanPlanType' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
      System.InvalidOperationException: The instance of entity type 'PnDemandPlanPlanType' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
         at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.set_State(EntityState value)
         at PnDemandPlan.DemandPlanService.CancelPnDemandPlanPlanTypeChanges(PnDemandPlanPlanType item) in C:\Projects\PNDemandPlan\server\Services\DemandPlanService.cs:line 3310
         at CallSite.Target(Closure , CallSite , Object )
         at PnDemandPlan.Pages.TestComponent.CancelButtonClick(MouseEventArgs args, Object data) in C:\Projects\PNDemandPlan\server\Pages\Test.razor.designer.cs:line 149
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Radzen.Blazor.RadzenButton.OnClick(MouseEventArgs args)
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

dotnet: fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
      Unhandled exception in circuit 'EM4W3UIqilTBhZx4ZKwsT9krQqklPbnydsGoMNNzsgo'.
      System.InvalidOperationException: The instance of entity type 'PnDemandPlanPlanType' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
         at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.set_State(EntityState value)
         at PnDemandPlan.DemandPlanService.CancelPnDemandPlanPlanTypeChanges(PnDemandPlanPlanType item) in C:\Projects\PNDemandPlan\server\Services\DemandPlanService.cs:line 3310
         at CallSite.Target(Closure , CallSite , Object )
         at PnDemandPlan.Pages.TestComponent.CancelButtonClick(MouseEventArgs args, Object data) in C:\Projects\PNDemandPlan\server\Pages\Test.razor.designer.cs:line 149
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Radzen.Blazor.RadzenButton.OnClick(MouseEventArgs args)
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

dotnet: info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/_blazor'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/_blazor?id=3OdmLKLjIwTqWY9qiY3o7g - - - 101 - - 25705.8875ms

Hi @markb,

This is indeed caused by disabling Entity Framework query tracking. When this is done the CancelXXX method no longer works as nothing tracks the original state of an entity. To address that you can edit the Click event of the Cancel button (it is in the EditTemplate of the column) - remove the invoke of CancelXXX and replace it with Execute C# await this.grid0.Reload()

Hi @korchev,

Thanks for that and it works perfectly on a single grid page.

I also have another page which has the original issue but, this page is more complex as it has a child datagrid (named "grid1") inside the template of the main parent grid on the page (named "grid0"). The child grid is populated on RowExpand of the parent grid by invoking the data source method to get the child data and then executing the C# ${event}.TheDetails = ${result}.ToList().

Using Execute C# await this.grid1.Reload() has no effect - presumably owing to how the grid is populated with data. Is there an alternative bit of code I can use in this scenario for the inline cancel edits button on the child grid (grid1)? Executing await this.grid0.Reload() does work but, that reloads the parent grid and causes the existing expanded row to collapse

In that case I can suggest to keep a copy of the original item when the Edit button is clicked. Create a property set to a new instance of your model and copy all its properties. Then on cancel set the properties back. Here is an example:

  1. When the Edit button is clicked create a new property "copy" and set its properties.

  2. When the Cancel button is clicked restore the entity properties from the copy.

Hi @korchev,

That works exactly as required :slight_smile: Many thanks for your input!