2014-02-06 33 views
0

我一直在試圖解決一段時間的問題。當你在asp gridview中用外鍵創建數據綁定時,你編輯一行並在dropbox中改變外鍵,例如保存更改並返回到視圖模式(編輯行= -1),外部值關鍵列消失(除非它沒有改變)。但是,如果刷新頁面(不再次發送數據),該值將正確顯示,並按預期進行更改。在asp gridview中更新後綁定外鍵與實體框架3.5

這也發生在繼承自asp網格視圖的SPGridView(sharepoint網格視圖)中。

讓我告訴你,只有更新方法非常簡單的例子: (我希望這不是太簡單)

網格

<asp:GridView 
    ID="exampleGridView" 
    runat="server" 
    DataKeyNames="Id" 
    AutoGenerateColumns="false" 
    OnRowUpdating="UpdateClick" 
    OnRowDataBound="RowDataBound"> 
    <Columns> 
     <asp:TemplateField HeaderText="Id"> 
      <ItemTemplate> 
       <asp:Label ID="Id" runat="server" Text='<%# Bind("Id") %>' /> 
      </ItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Login"> 
      <ItemTemplate> 
       <asp:Label ID="Login" runat="server" Text='<%# Bind("Login") %>' /> 
      </ItemTemplate> 
      <EditItemTemplate> 
       <asp:TextBox ID="EditLoginTextBox" runat="server" Text='<%# Bind("Login") %>' Enabled="false" /> 
      </EditItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Role"> 
      <ItemTemplate> 
       <asp:Label ID="Role" runat="server" Text='<%# Bind("Role.Title") %>' /> 
      </ItemTemplate> 
      <EditItemTemplate> 
       <asp:DropDownList ID="EditRoleDropDownList" runat="server" /> 
      </EditItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Action"> 
     <ItemTemplate> 
      <asp:LinkButton ID="EditLinkBtn" runat="server" CommandName="Edit" Text="edit" /> 
     </ItemTemplate> 
     <EditItemTemplate> 
      <asp:LinkButton ID="UpdateLinkBtn" runat="server" CommandName="Update" Text="update" /> 
     </EditItemTemplate> 
    </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

後面的代碼

protected void UpdateClick(object sender, System.Web.UI.WebControls.GridViewUpdateEventArgs e) 
{ 
    // context taken from constructor, created at the beginning of a request and disposed at the end of a request 
    User user = this.ctx.Users.First(u => u.Id == id); 

    GridViewRow row = this.exampleGridView.Rows[e.RowIndex]; 

    user.Login = ((TextBox)row.FindControl("EditLoginTextBox")).Text; 

    int roleId =int.Parse(((DropDownList)row.FindControl("EditRoleDropDownList")).SelectedValue); 
    if (user.Role.Id != roleId) 
    { 
     user.Role = ctx.Attach(new Role 
     { 
      Id = roleId 
     }); 
    } 

    this.ctx.SaveChanges(); 
    this.exampleGridView.EditIndex = -1; 
    this.BindGrid(); 
} 

protected void RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
    if (e.Row.RowType == DataControlRowType.DataRow && 
     (e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit) 
    { 
     var user = (User)e.Row.DataItem; 

     var editRoleDropDownList = (DropDownList)e.Row.FindControl("EditRoleDropDownList"); 
     this.BindRoleDropDownList(editRoleDropDownList); 
     editRoleDropDownList.SelectedValue = user.Role.Id.ToString(); 
    } 
} 

private void BindGrid() 
{ 
    this.exampleGridView.DataSource = this.ctx.Users.Include(u => u.Role); 
    this.exampleGridView.DataBind(); 
} 

private void BindRoleDropDownList(DropDownList roleDropDownList) 
{ 
    // list of roles 
    if (this.cachedRoles == null) 
    { 
     this.cachedRoles = this.ctx.Roles.ToList(); 
    } 

    roleDropDownList.DataSource = this.cachedRoles; 
    roleDropDownList.DataValueField = "Id"; 
    roleDropDownList.DataTextField = "Name"; 
    roleDropDownList.DataBind(); 
} 

回答

0

答案比我想的要簡單。該proble是在更新方法:

int roleId = int.Parse(((DropDownList)row.FindControl("EditRoleDropDownList")).SelectedValue); 
if (user.Role.Id != roleId) 
{ 
    // this is the problem 
    user.Role = ctx.Attach(new Role 
    { 
     Id = roleId 
    }); 
} 

的問題是,我重寫與具有Role.Title等於顯然空字符串這個新對象的角色。對象停留在那裏。所以適當的解決辦法如下:

int roleId = int.Parse(((DropDownList)row.FindControl("EditRoleDropDownList")).SelectedValue); 
if (user.Role.Id != roleId) 
{ 
    user.Role = this.ctx.Roles.First(r => r.Id == roleId); 
}