今天真是的很不幸,又出现了以前遇到的问题
上一次虽然解决了,但也没找到原因,
这是上次的问题
(
在用objectDataSource控件进行操作时出现以下问题:
ObjectDataSource“ObjectDataSource1”未能找到接受“PhotoType”类型的参数的非泛型方法“DeletePhotoType”。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.InvalidOperationException: ObjectDataSource“ObjectDataSource1”未能找到接受“PhotoType”类型的参数的非泛型方法“DeletePhotoType”。
想了半天后,将原来的方法DeletePhotoType(int id)中的参数改为DeletePhotoType(PhotoType p)后能正常删除
)
这次本也相这样解决,可以因为这次是用数据集(dataset.xsd)自动生成的查询语句,上面的没办法解决,在网上找了许多资料,说得比较全的是这样说的
OldValuesParameterFormatString
在使用前面的例子里,请注意分配给 UpdateCommand 的 Update 语句中的参数的命名约定。Update和Delete的参数都采用默认的列命名方式,例如ProductDAL.cs里的DeleteProduct定义如下:
public void DeleteProduct(int ProductId)
{
SqlConnection con = new SqlConnection(_connectionString);
string deleteString = "DELETE FROM Products WHERE ProductID=@ProductID";
SqlCommand cmd = new SqlCommand(deleteString, con);
cmd.Parameters.AddWithValue("@ProductID", ProductId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
如果你想更改列的名称,例如更改DeleteProduct如下
public void DeleteProduct(int old_ProductId)
{
SqlConnection con = new SqlConnection(_connectionString);
string deleteString = "DELETE FROM Products WHERE ProductID=@ProductID";
SqlCommand cmd = new SqlCommand(deleteString, con);
cmd.Parameters.AddWithValue("@ProductID", old_ProductId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
那么你在运行时将出现错误如图2-34
图2-34 参数不匹配错误
这是因为GridView 和其他数据绑定控件调用 Update 操作的自动功能需依赖此命名约定才能工作。参数的命名预期应与 SelectCommand 返回的关联字段值相同。使用此命名约定使得数据绑定控件传递给数据源的值与 SQL Update 语句中的参数相对应成为可能。
此默认命名约定的使用假设 Keys 和 Values 字典的内容相互排斥 -- 即用户能够在数据绑定控件处于编辑模式时更新的字段值的命名应该与用于匹配要更新的行的字段值(对于 SqlDataSource,这些字段值在 WHERE 子句中)的命名不同。考虑这点的另一种方式是在 DataKeyNames 上设置的任何字段都应该设置为只读或在数据绑定控件中(例如在 GridView Columns 集合中)不可见。虽然键字段为只读的情况很普遍,但是存在一些有效的方案,其中您将希望能够更新同时还用于匹配要更新的数据行的字段。
例如,如果我们将Products数据库的ProductID列在设计表格结构时设置为nvarchar,它存放的是图书ISDN编号,该编号并不是递增的,因此在运行时,您可以更改ProductID的只,前提是主要不重复即可。
这样我们就需要将该ProductID列设置为ReadOnly=”false”以便允许编辑,另一方面,为了确认哪条记录被更新还需要传递该列的只到更新/删除方法,所以还需要将DataKeyNames设置为ProductID。
这样GridView 将在 Keys 字典中传递该字段的旧值,而在 Values 字典中传递该字段的新值。仍以UpdateProduct为例,当将ProductID的ReadOnly设置为”false”,并且将DataKeyNames设置为ProductID后,对于前面介绍的这条记录
ProductID ProductName CategoryID Price InStore Description
24 生物技术 7 9.0000 2 生物技术丛书
我想将ProductID更改为ISBN001,此时传递给UpdateProduct的方法是:
key value
{"24 " , "ISBN001" }
{"@ProductName", "生物技术"}
{"@CategoryID", "7" }
{"@price", "9.0000"}
{"@InStore", "2" }
{"@Description", "生物技术丛书"}
我们之所以需要这两个值是因为,利用“24”我们需要获取该记录,利用“ISBN001”我们需要知道将来要把24更新为什么值。因为这样我们就需要区分Key和value的值。为了区别这两类值,需要在 SQL 语句中以不同的方式命名参数,例如:
<asp:SqlDataSource runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [productid], [productname], [categoryID], [Price],[InStore],[Description] FROM [products]"
UpdateCommand="UPDATE [products] SET [productid] = @productid, [productname] = @productname, [categoryid] = @categoryid, [price] = @price,description=@Description WHERE [productid] = @old_productid"
DeleteCommand="DELETE FROM [products] WHERE [productid] = @ old_productid "/>
OldValuesParameterFormatString="old_{0}"
在上面例子中,参数名称 @old_productid 用于引用Key字段的原始值24,@productid 用于引用新Value字段的新值ISBN001。其中旧值和新值的命名是通过OldValuesParameterFormatString来完成。
SqlDataSource 的 OldValuesParameterFormatString 属性也被设置为有效的 .NET Framwork 格式字符串,以指示应该如何重命名 Keys 字典中的参数。当 SqlDataSource 的 ConflictDetection 属性设置为 CompareAllValues 时,此格式字符串还应用于数据绑定控件传递的非键字段的旧值。对于 Delete 操作,SqlDataSource 默认仅应用 Keys 字典(不存在用于删除操作的新值),并使用 OldValuesParameterFormatString 属性的值格式化键参数名称。代码2-14 FormatPara_ObjectDataSource.aspx演示了上面的说明。
<asp:ObjectDataSource runat="server" DeleteMethod="DeleteProduct"
SelectMethod="GetProduct" TypeName="ProductDAL" UpdateMethod="UpdateProduct"
OldValuesParameterFormatString="old_{0}">
</asp:ObjectDataSource>
<asp:GridView DataKeyNames="ProductID" runat="server" AutoGenerateDeleteButton="True"
AutoGenerateEditButton="True" CellPadding="4" DataSourceID="ObjectDataSource1" AutoGenerateColumns="false"
Font-Names="Verdana" Font-Size="XX-Small" ForeColor="#333333" GridLines="None"
>
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID"/>
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" />
<asp:BoundField DataField="Price" HeaderText="Price" SortExpression="Price" />
<asp:BoundField DataField="InStore" HeaderText="InStore" SortExpression="InStore" />
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
</Columns>
</asp:GridView>
代码2-14FormatPara_ObjectDataSource.aspx部分源代码
同时将DeleteUpdate方法改成代码2-15
public void DeleteProduct(int old_ProductId)
{
SqlConnection con = new SqlConnection(_connectionString);
string deleteString = "DELETE FROM Products WHERE ProductID=@ProductID";
SqlCommand cmd = new SqlCommand(deleteString, con);
cmd.Parameters.AddWithValue("@ProductID", old_ProductId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
代码2-15 DeleteProduct方法
上面代码的运行结果和图2-33一样。然而在使用上面代码时,可能有些人将2-14的代码写成如下的形式:
<asp:ObjectDataSource runat="server" DeleteMethod="DeleteProduct"
SelectMethod="GetProduct" TypeName="ProductDAL" UpdateMethod="UpdateProduct"
OldValuesParameterFormatString="old_{0}">
<DeleteParameters>
<asp:Parameter Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>
如果运行此段代码则出现错误如图2-35,这是因为我们需要默认的参数ProductID,如果您显式设置则多此一举,系统认为你需要传递ProductID和old_Product。如果真的要设置应该设置old_Product,也就是
<asp:ObjectDataSource runat="server" DeleteMethod="DeleteProduct"
SelectMethod="GetProduct" TypeName="ProductDAL" UpdateMethod="UpdateProduct"
OldValuesParameterFormatString="old_{0}">
<DeleteParameters>
<asp:Parameter Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>
这种方法同样使用UpdateMethod。
看了个半懂,不过还是不知道为什么dataset自动生成的语句也会错,后来发现,只要把数据库里定义ID时,把标识选为 是(不用于复制)
我们一般选标识只是选为是,所以常出现上面的错误,问题解决了,可是原因不是很清楚.