【问题标题】:DataTable not retaining added rowsDataTable 不保留添加的行
【发布时间】:2016-05-19 15:32:28
【问题描述】:

这个网页应该这样流动:

调用 populateTeamMembers(),它首先检查数据表是否没有行(表明这是第一次调用该函数),如果它查询 SQL 以查看谁是现有团队成员,则加载该数据表进入数据表 sqlTeamMembers

此函数还检查第二个数据表 newTeamMembers 中是否有任何行,如果有,则将 newTeamMembers 的内容合并到 sqlTeamMembers 中。第一次加载页面时,newTeamMembers 数据表应始终为空,因此不会执行合并。

最后,现在 sqlTeamMembers 应该包含我们需要的每个人,它将它绑定到一个 gridview 以显示在网页上。

显示后,网格视图下会出现一个下拉列表,其中包含可以添加到团队中的员工列表。如果在 ddl 上更改了所选索引,您会收到回发并调用 selectedIndexChanged()。

selectedIndexChanged() 中的逻辑是将选定的个人信息查询到数据表中,如果他们已经分配到不同的团队,则会警告用户,然后继续将员工添加到 newTeamMembers 数据表中。

最后再次调用populateTeamMembers(),此时newTeamMembers数据表中有数据,进行合并,再次绑定到gridView。

由于两个数据表 sqlTeamMembers 和 newTeamMembers 的性质,我已经在我的类的头部初始化了它们,所以它们应该可以被所有函数访问。

到目前为止,它可以向 sqlTeamMembers 添加一个新行,但如果我尝试进行第二次添加,它会清除第一次添加。 出于某种原因,newTeamMembers 没有保留新行,它只包含 selectedIndexChanged() 创建的最新添加。

如何让 newTeamMembers 在每次调用 selectedIndexChanged() 时保留新行?

public partial class Personnel_Admin_Teams : System.Web.UI.Page
{

SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["WebServerConnectionString"].ConnectionString);
SqlDataReader myreader = default(SqlDataReader);
SqlCommand cmd = new SqlCommand();


string sqlStr;
DataTable sqlTeamMembers = new DataTable();
DataTable newTeamMembers = new DataTable();
...



protected void populateTeamMembers(string TeamID)
{
    if (sqlTeamMembers.Rows.Count == 0)
    {
        /***  Read Team Members with Matching TeamID from Employees Table ***/
        cnn.Open();
        sqlStr = "SELECT [ID], [LastName]+', '+[FirstName] AS [Name], ISNULL([TeamRole], '') AS [TeamRole] FROM [Employees] WHERE [TeamID] = " + TeamID + ";";
        cmd = new SqlCommand(sqlStr, cnn);
        sqlTeamMembers.Load(cmd.ExecuteReader());
        cnn.Close();
    }



    if (newTeamMembers.Rows.Count > 0)
    {
        sqlTeamMembers.Merge(newTeamMembers);
    }

    gvTeamMembers.DataSource = sqlTeamMembers;
    gvTeamMembers.DataBind();


    try
    {
        for (int i = 0; i < gvTeamMembers.Rows.Count; i++)
        {

            DropDownList ddlTeamRole = gvTeamMembers.Rows[i].Cells[2].FindControl("ddlTeamRole") as DropDownList;
            string txtTeamRole = sqlTeamMembers.Rows[i][2].ToString();
            txtTeamRole = txtTeamRole.Replace("'", "''");

            ddlTeamRole.SelectedValue = txtTeamRole;
        }
    }

    catch (Exception ex)
    {
        ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), "class", "alert(\"There was an error: " + ex + "\");", true);
    }
}



selectedIndexChanged()  
{    


        cnn.Open();
        sqlStr = "SELECT [ID], [LastName]+', '+[FirstName] AS [Name], ISNULL([TeamRole], '') AS [TeamRole], ISNULL([TeamID], '0') FROM [Employees] WHERE [ID] = " + ddlAllEmployees.SelectedValue + ";";
        cmd = new SqlCommand(sqlStr, cnn);
        DataTable addOneMember = new DataTable();
        addOneMember.Load(cmd.ExecuteReader());
        cnn.Close();


        int empTeamID = Convert.ToInt32(addOneMember.Rows[0][3]);

        /*** If DT has not been used yet, establish columns ***/
        if (newTeamMembers.Columns.Count == 0)
        {
            newTeamMembers.Columns.Add("ID", typeof(int));
            newTeamMembers.Columns.Add("Name", typeof(string));
            newTeamMembers.Columns.Add("TeamRole", typeof(string));
        }

        /*** Remove TeamID Column before merging data back to primary DataTable, perform merge ***/
        addOneMember.Columns.RemoveAt(3);
        newTeamMembers.Merge(addOneMember);



    if (empTeamID != 0)
        {
            sqlStr = "SELECT [TeamLocation]+' | '+[Department]+' | '+[Type]+' | '+[Team]+' | '+[Shift] AS [Team] FROM [Teams] WHERE [ID] =" + empTeamID + ";";
            cmd = new SqlCommand(sqlStr, cnn);
            cnn.Open();
            myreader = cmd.ExecuteReader();
            myreader.Read();

            string existingTeam = myreader[0].ToString();

            myreader.Close();
            cnn.Close();

            ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), "class", "alert(\"Warning: User is currently assigned to another team.  Employee will be removed from " + existingTeam + " when you save this page.\");", true);

        }
    }

【问题讨论】:

    标签: c# asp.net gridview datatable


    【解决方案1】:

    您需要了解一些事情。

    网页是无状态的,这意味着在它的初始传递和后续 PostBacks 中,您负责通过一些持久性介质保存和恢复状态。

    很多服务器控件都可以为您执行此操作,但您选择通过 DataTables 管理所有这些,因此您需要实现数据持久性。对于数据库查询结果,SqlDataSource 控件使用应用程序缓存。您也应该以编程方式使用它:

    公共部分类 Personnel_Admin_Teams:System.Web.UI.Page { 数据表 sqlTeamMembers = null; 数据表 newTeamMembers = null; protected void Page_Load(对象发送者,EventArgs e){ 如果(!Page.IsPostBack){ if(Application.Cache["sqlTeamMembers"] == null) Application.Cache["sqlTeamMembers"] = new DataTable(); if(Application.Cache["newTeamMembers"] == null) Application.Cache["newTeamMembers"] = new DataTable(); } sqlTeamMembers = (DataTable) Application.Cache["sqlTeamMembers"]; newTeamMembers = (DataTable) Application.Cache["newTeamMembers"]; // 注意: sqlTeamMembers 将为空,直到您调用 // populateTeamMembers() 所以没有硬性规定 // 关于 PageLoad 期间的绑定。每次需要时绑定 // 反映变化。 gvTeamMembers.DataSource = sqlTeamMembers; gvTeamMembers.DataBind(); } }

    另外,只是为了验证,DataTables 不是实时的,打开与数据库的连接。对 DataTables 的更改不会自动写回您的数据库。您必须进行适当的 INSERT/UPDATE SQL 调用。

    【讨论】:

    • 您说得对,数据持久性实际上是问题所在。无论出于何种原因,我无法调用此站点上的应用程序缓存,所以现在我选择使用会话变量根据需要来回传递 sqlTeamMembers 数据表。
    • 关于保存到SQL,这里想要的效果是还没有修改SQL。用户应根据需要修改加载的数据表,最后将有机会保存或取消更改,此时数据表要么被简单地丢弃,要么将其值保存回 SQL。
    【解决方案2】:

    我认为问题在于这条线的位置:

    DataTable newTeamMembers = new DataTable();
    

    由于它位于类的开头,因此每次加载页面时都会运行它,这意味着每次加载页面,包括页面是回发的时候。例如,当用户单击按钮以添加新的团队成员时,就会发生回发。然后将包含用户条目的页面发送回服务器。

    您正在寻找的行为是在第一次页面加载时初始化一个新的newTeamMembers,但在页面是回发时不是。为了解决这个问题,在类的顶部声明newTeamMembers,但只有在页面不是回发时才初始化它,通过在页面加载事件中检查这个:

    public partial class Personnel_Admin_Teams : System.Web.UI.Page
    {
        DataTable newTeamMembers;
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack) //page is loaded for the first time
            {
                newTeamMembers = new DataTable();
            }
        }
        //rest of the code
    }
    

    【讨论】:

    • 大部分正确。 DataTable 保存在哪里?变量newTeamMembers 在回发时仍未初始化,因为它从未从持久位置读回,例如Application.Cache
    • 是的,你完全正确。 ViewState 是另一种选择,但由于它默认存储在客户端上并且 DataTable 可能很大,因此您的缓存解决方案似乎是最佳选择。 :)
    • 我会避免 ViewState 用于数据集,因为它作为隐藏字段与渲染页面的其余部分一起传输。想象一个返回数千行的查询
    • 没错,这就是为什么您更喜欢应用缓存的答案。 :)
    • 是的 - 我看到了 ViewState 这个词并停止阅读,抱歉。
    猜你喜欢
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 2014-03-19
    • 2012-10-03
    • 2014-05-20
    相关资源
    最近更新 更多