【蛙蛙推荐】GridView和ObjectDataSource更新数据的一个Bug
相信大家在利用ObjectDataSource更新GridView或者FormView数据的时候一定遇到过这样的错误。
ObjectDataSource 'ods1' could not find a non-generic method 'ModifyPhrase' that has parameters: PID, pgid, content, Context.
你可以用google搜索一下这个错误,国内国外都有讨论,有人说这是微软的一个Bug。其实是因为GridView自动给数据源更新方法生成的参数不正确引起的。GridView在Updating事件里传递给DataSource的参数有DataKeyNames字段,以及你编辑状态下非readonly的字段,如果这几个字段加起来和数据源声明的几个参数对应起来,那么就会成功的调用数据源的更新方法,否则就会出现类似上面的错误。解决这个问题就是在Updating事件里处理传过去的参数。我做了一个例子。
这是数据源的代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
public class Entity
{
public Entity(int id, string name)
{
m_id = id;
m_name = name;
}
int m_id;
public int Id
{
get { return m_id; }
set { m_id = value; }
}
string m_name;
public string Name
{
get { return m_name; }
set { m_name = value; }
}
}
[DataObject]
public class BLL
{
static Dictionary<int, string> dict = new Dictionary<int, string>();
public BLL()
{
}
[DataObjectMethod(DataObjectMethodType.Insert, true)]
public void Add(int id, string name)
{
dict.Add(id, name);
}
[DataObjectMethod(DataObjectMethodType.Select, true)]
public Entity[] GetAll()
{
Entity[] entities = new Entity[dict.Count];
int i = 0;
foreach (KeyValuePair<int, string> kvp in dict)
{
entities[i] = new Entity(kvp.Key, kvp.Value);
i++;
}
return entities;
}
[DataObjectMethod(DataObjectMethodType.Update, true)]
public void Update(int pid, string pname)
{
dict[pid] = pname;
}
[DataObjectMethod(DataObjectMethodType.Delete, true)]
public void Delete(int id)
{
dict.Remove(id);
}
}
using System.Collections.Generic;
using System.ComponentModel;
public class Entity
{
public Entity(int id, string name)
{
m_id = id;
m_name = name;
}
int m_id;
public int Id
{
get { return m_id; }
set { m_id = value; }
}
string m_name;
public string Name
{
get { return m_name; }
set { m_name = value; }
}
}
[DataObject]
public class BLL
{
static Dictionary<int, string> dict = new Dictionary<int, string>();
public BLL()
{
}
[DataObjectMethod(DataObjectMethodType.Insert, true)]
public void Add(int id, string name)
{
dict.Add(id, name);
}
[DataObjectMethod(DataObjectMethodType.Select, true)]
public Entity[] GetAll()
{
Entity[] entities = new Entity[dict.Count];
int i = 0;
foreach (KeyValuePair<int, string> kvp in dict)
{
entities[i] = new Entity(kvp.Key, kvp.Value);
i++;
}
return entities;
}
[DataObjectMethod(DataObjectMethodType.Update, true)]
public void Update(int pid, string pname)
{
dict[pid] = pname;
}
[DataObjectMethod(DataObjectMethodType.Delete, true)]
public void Delete(int id)
{
dict.Remove(id);
}
}
这是页面的代码
<%@ Page Language="C#" Debug="true" Trace="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void LinkButton1_Click(object sender, EventArgs e)
{
int id;
int.TryParse(txtID.Text, out id);
new BLL().Add(id, txtName.Text);
GridView1.DataBind();
}
protected void ObjectDataSource1_Updating(object sender, ObjectDataSourceMethodEventArgs e)
{
//update方法本来有俩参数pid和name,而key是id,而修改的数据是datafeild是name
//所以我们要转换一下,并把不用的参数去调,另外参数不区分大小写
e.InputParameters["pid"] = e.InputParameters["Id"];
e.InputParameters["pname"] = e.InputParameters["name"];
e.InputParameters.Remove("id");
e.InputParameters.Remove("name");
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>测试GridView的编辑功能</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<!--要想使用GridView的编辑功能,要设置DataKeyNames属性,并把主键字段设置成ReadOnly
字段声明这里一定要包含update方法需要的参数,然后在数据源的Updating事件里进行转换
否则有些参数无法赋值了
-->
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" DataSourceID="ObjectDataSource1" DataKeyNames="ID" AutoGenerateColumns="False">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True" />
<asp:BoundField DataField="Name" HeaderText="Name" />
</Columns>
<EmptyDataTemplate>
没有数据
</EmptyDataTemplate>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DeleteMethod="Delete"
InsertMethod="Add" SelectMethod="GetAll"
TypeName="BLL" UpdateMethod="Update" OnUpdating="ObjectDataSource1_Updating" >
<DeleteParameters>
<asp:Parameter Name="id" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="pid" Type="Int32" />
<asp:Parameter Name="pname" Type="String" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="id" Type="Int32" />
<asp:Parameter Name="name" Type="String" />
</InsertParameters>
</asp:ObjectDataSource>
<br />
ID<asp:TextBox ID="txtID" runat="server"></asp:TextBox><br />
NAME<asp:TextBox ID="txtName" runat="server"></asp:TextBox><br />
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">添加</asp:LinkButton></div>
</form>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void LinkButton1_Click(object sender, EventArgs e)
{
int id;
int.TryParse(txtID.Text, out id);
new BLL().Add(id, txtName.Text);
GridView1.DataBind();
}
protected void ObjectDataSource1_Updating(object sender, ObjectDataSourceMethodEventArgs e)
{
//update方法本来有俩参数pid和name,而key是id,而修改的数据是datafeild是name
//所以我们要转换一下,并把不用的参数去调,另外参数不区分大小写
e.InputParameters["pid"] = e.InputParameters["Id"];
e.InputParameters["pname"] = e.InputParameters["name"];
e.InputParameters.Remove("id");
e.InputParameters.Remove("name");
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>测试GridView的编辑功能</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<!--要想使用GridView的编辑功能,要设置DataKeyNames属性,并把主键字段设置成ReadOnly
字段声明这里一定要包含update方法需要的参数,然后在数据源的Updating事件里进行转换
否则有些参数无法赋值了
-->
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" DataSourceID="ObjectDataSource1" DataKeyNames="ID" AutoGenerateColumns="False">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True" />
<asp:BoundField DataField="Name" HeaderText="Name" />
</Columns>
<EmptyDataTemplate>
没有数据
</EmptyDataTemplate>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DeleteMethod="Delete"
InsertMethod="Add" SelectMethod="GetAll"
TypeName="BLL" UpdateMethod="Update" OnUpdating="ObjectDataSource1_Updating" >
<DeleteParameters>
<asp:Parameter Name="id" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="pid" Type="Int32" />
<asp:Parameter Name="pname" Type="String" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="id" Type="Int32" />
<asp:Parameter Name="name" Type="String" />
</InsertParameters>
</asp:ObjectDataSource>
<br />
ID<asp:TextBox ID="txtID" runat="server"></asp:TextBox><br />
NAME<asp:TextBox ID="txtName" runat="server"></asp:TextBox><br />
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">添加</asp:LinkButton></div>
</form>
</body>
</html>