Rows removed from a datatable are also removed from the session variable that created the datatable

I am noticing some strange behavior when working with datatables stored in session variables. Removing a row from a datatable that is created from a session variable appears to also modify the session variable as demonstrated below.

<asp:GridView ID="gvResults" runat="server" DataKeyNames="id">
<Columns>
    <asp:TemplateField ShowHeader="False">
        <ItemTemplate>
            <asp:Button ID="btnSelectUserToRemove" runat="server" CausesValidation="false" CommandName="Remove" Text="Select" CommandArgument='<%# Eval("id") %>' OnCommand="Command" />
        </ItemTemplate>
    </asp:TemplateField>
</Columns>
</asp:GridView>


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

public partial class Test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DataTable dtResults = new DataTable();
            dtResults.Columns.Add("id");

            dtResults.Rows.Add();
            dtResults.Rows[0]["id"] = "1";
            dtResults.Rows.Add();
            dtResults.Rows[1]["id"] = "2";

            Session["id"] = dtResults;
            gvResults.DataSource = dtResults;
            gvResults.DataBind();
        }
    }

    protected void Command(object sender, CommandEventArgs e)
    {
        if (e.CommandName == "Remove")
        {
            DataTable dtTemp = (DataTable)Session["id"];
            for (Int32 i = 0; i < dtTemp.Rows.Count; i++)
            {
                if (e.CommandArgument.ToString() == dtTemp.Rows[i]["id"].ToString())
                {
                    dtTemp.Rows[i].Delete(); //Should just remove the row from the datatable.
                }
            }
            dtTemp.AcceptChanges();
        }
        DisplayData();
    }

    protected void DisplayData()
    {
        gvResults.DataSource = (DataTable)Session["id"];
        gvResults.DataBind(); //Should display both rows because I did not save the modified datatable back to this session variable.
    }
}

I am not saving the modified dtTemp datatable back to the Session["id"] variable. It is my understanding that there should be 1 row in dtTemp, because one row was deleted, and 2 rows in Session["id"] when calling DisplayData. However, only one row is displayed in the gridview after DisplayData runs.

I am hoping there is someone out there that can shed some light on why this is happening.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

It’s because dtTemp and the session variable are object references that both point to the same object.

Method 2

This line:

DataTable dtTemp = (DataTable)Session["id"];

Does not do what you think it does. Since the DataTable is a reference type, you’re just grabbing a pointer to that object’s location in memory (which happens to be in the SessionState variable), not creating a fresh copy of it.

If you want to operate on the DataTable without modifying the one in Session, you’ll need to look into a Clone pattern, like How do you do a deep copy of an object in .NET (C# specifically)?


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x