Blazor Radzen DataGrid - Possible memory reference bug

I've spent 2 hours on this one and can't seem to figure it out. I have lists of original and modified objects (I'm not using Entity Framework tracking). The modified list is bound to a RadzenGrid. The way I'm setting the modified list should cut all references to the original. When I edit a row and handle the SaveRow event, both the original and modified lists' object is changed. It's not making sense to me, I tried every C# trick to cut the reference. Here's the code:

<RadzenGrid @ref="controllerGrid" Data="@modifiedControllers" TItem="PinnacleController" AllowFiltering="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
FilterMode="FilterMode.Simple" AllowPaging="true" AllowSorting="true" PageSize="9" EditMode="DataGridEditMode.Multiple" RowCreate="@InsertRow" CellRender="@CellRender">





<RadzenTextBox @bind-Value="controller.Name" Style="width:97%" />




<button class="select-btn" @onclick="@(args => EditRow(controller))">Edit


<button class="select-btn" @onclick="@((args) => SaveRow(controller))">Save
<button class="delete-btn" @onclick="@((args) => CancelEdit(controller))">Cancel




<button class="delete-btn" @onclick="@(args => DeleteRow(controller))">Delete


<button class="delete-btn" @onclick="@(args => DeleteRow(controller))">Delete




<button class="select-btn" @onclick="@(args => SelectRow(controller))">Select



@code {
private RadzenGrid controllerGrid;
private List modifiedControllers;
private List originalControllers;
private List<RecordModification> pendingTransactions = new List<RecordModification>();

protected override async Task OnInitializedAsync()
{
    await GetControllers();
}

private async Task GetControllers()
{
    originalControllers = await httpClient.GetFromJsonAsync<List<PinnacleController>>(httpClient.BaseAddress + "myapicall");
    modifiedControllers = new List<PinnacleController>(originalControllers);
}

private void EditRow(PinnacleController controller)
{
controllerGrid.EditRow(controller);
}

private void SaveRow(PinnacleController controller)
{
PinnacleController orig = (from x in originalControllers where x.Id == x.Id select x).First();

    if (orig.Name != controller.Name)
    {
        controllerGrid.UpdateRow(controller);
        pendingTransactions.Add(new RecordModification<PinnacleController>()
        {
            Modified = controller,
            Original = orig,
            Rowid = controller.Rowid,
            RecordStatus = RecordStatus.Updated
        });
    }
    else
    {
        controllerGrid.CancelEditRow(controller);
    }
}

}

This creates a new list which contains the original objects:

modifiedControllers = new List<PinnacleController>(originalControllers);

This is how the List class behaves. It will not create copies of the items. Unrelated to RadzenGrid.

Thank you @korchev for your response. Why is it that orig.Name always equals controller.Name in the SaveRow method, when it is modifiedControllers that is databound to the grid? The Name property is what I'm editing in the grid. What am I doing wrong?

private void SaveRow(PinnacleController controller)
{
    PinnacleController orig = (from x in originalControllers where x.Id == controller.Id select x).First();

    if (orig.Name != controller.Name)
    {
        controllerGrid.UpdateRow(controller);
        pendingTransactions.Add(new RecordModification<PinnacleController>()
        {
            Modified = controller,
            Original = orig,
            Rowid = controller.Rowid,
            RecordStatus = RecordStatus.Updated
        });
    }
    else
    {
        controllerGrid.CancelEditRow(controller);
    }
}

Thanks

Because they are the same instance. Read my reply again.

Sorry about that. I misunderstood you. You can delete my post if you want as this is not a Radzen issue. Thanks

Hi Scott

I have fallen foul of this same issue before. Korchev is right they are both pointing to the same instance.

One way around this, if the dataset is not too large, is to serialize the list into a variable and then deserialize the variable into the new list.

This will break the link.

Others may have better solutions.

HTH

Sean

1 Like

Thanks @Sean. That was one possible solution I was looking at. On my entities, I have a Clone() method built-in. So what I ended up doing was looping through the original list, then adding the cloned object to the modified list and it worked like a charm. Like you said though, with a large dataset, it'll come down to whichever way is most efficient. I appreciate the help.

foreach (PinnacleController pc in originalControllers)
    {
        modifiedControllers.Add(pc.Clone());
    }

Here's a link that takes a look at performance in such scenarios: