Asp.net 使用实体框架3.5在asp gridview中更新后绑定外键
我试图解决这些问题已经有一段时间了。在asp gridview中使用外键创建数据绑定时,编辑一行并在dropbox中更改外键。例如,保存更改并返回视图模式(编辑行=-1),外键列中的值将消失(除非未更改)。但是,如果刷新页面(不再次发送数据),则会正确显示值,并按预期进行更改 这也发生在从asp网格视图继承的SPGridView(sharepoint网格视图)中 让我向您展示一个仅使用更新方法的非常简化的示例: (希望不要太简单) 网格Asp.net 使用实体框架3.5在asp gridview中更新后绑定外键,asp.net,entity-framework,Asp.net,Entity Framework,我试图解决这些问题已经有一段时间了。在asp gridview中使用外键创建数据绑定时,编辑一行并在dropbox中更改外键。例如,保存更改并返回视图模式(编辑行=-1),外键列中的值将消失(除非未更改)。但是,如果刷新页面(不再次发送数据),则会正确显示值,并按预期进行更改 这也发生在从asp网格视图继承的SPGridView(sharepoint网格视图)中 让我向您展示一个仅使用更新方法的非常简化的示例: (希望不要太简单) 网格 <asp:GridView ID="exa
<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();
}
答案比我想象的要简单。问题在于更新方法:
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);
}