2016-05-19 20 views
0

此网页应流这样:数据表不保留添加的行

呼叫要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); 

     } 
    } 

回答

1

有你需要了解的几件事。

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

很多服务器控件都可以为你做到这一点,但你选择通过DataTables来管理所有这些,所以你需要实现数据持久性。对于数据库查询结果,SqlDataSource控件使用应用程序缓存。你应该使用它以编程方式:

 
    public partial class Personnel_Admin_Teams : System.Web.UI.Page 
    { 
     DataTable sqlTeamMembers = null; 
     DataTable newTeamMembers = null; 

     protected void Page_Load(object sender, EventArgs e) { 
     if(!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"]; 

     // NOTE: sqlTeamMembers will be null until you make that call to 
     //  populateTeamMembers() so there is no hard and fast rule 
     //  about binding during PageLoad. Bind every time you need 
     //  to reflect changes. 
     gvTeamMembers.DataSource = sqlTeamMembers; 
     gvTeamMembers.DataBind(); 
     } 

    } 

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

+0

你是真的,数据持久性实际上是问题。无论出于何种原因,我都无法调用该站点上的应用程序缓存,因此,现在我选择使用会话变量根据需要来回传递sqlTeamMembers数据表。 –

+0

关于保存到SQL,这里所期望的效果是不修改SQL。用户应该根据需要修改加载的数据表,并在结束时给予机会进行SAVE或CANCEL更改,此时数据表被简单地丢弃,或将其值保存回SQL。 –

0

我认为这个问题是这条线的位置:

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 
} 
+0

大部分正确。 DataTable在哪里被持久化?变量'newTeamMembers'在回发时仍然未初始化,因为它永远不会从持久位置读回,如'Application.Cache' – fnostro

+1

是的,你完全正确。 'ViewState'是另一种选择,但由于默认情况下它存储在客户端上,并且DataTable的大小可能很大,因此使用缓存的解决方案似乎是最佳选择。 :) – Puppetmupp

+0

我会避免使用数据集的'ViewState',因为它是以隐藏字段的形式与其他呈现页面一起传输的。想象一下,返回几千行的查询 – fnostro