Question

I have a gridview (CustomerDetails) with editing enabled. When i click the edit button and update one of the 5/6 fields (i changed all fields to templatefield and then set the edittemplate to a label for the fields i didnt want to be editable) i get an error:

"ObjectDataSource 'ObjectDataSource1' could not find a non-generic method 'UpdateCustomerAddressZip' that has parameters: CustomerID, CustomerAddressOne, CustomerAddressTwo, CustomerZip, original_CustomerID"

The object datasource code is

    <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" InsertMethod="InsertCustomer"
        OldValuesParameterFormatString="original_{0}" SelectMethod="CustomerDetails" UpdateMethod="UpdateCustomerAddressZip"
        TypeName="Enterprise.CustomerEntityLayer">
        <InsertParameters>
            <asp:Parameter Name="CustomerID" Type="Int32" />
            <asp:Parameter Name="CustomerAddressOne" Type="String" />
            <asp:Parameter Name="CustomerAddressTwo" Type="String" />
            <asp:Parameter Name="CustomerZip" Type="String" />
        </InsertParameters>
        <UpdateParameters>
        <asp:Parameter Name="CustomerID" Type="Int32" />
        <asp:Parameter Name="CustomerAddressOne" Type="String" />
        <asp:Parameter Name="CustomerZip" Type="String" />
        </UpdateParameters>
        <SelectParameters>
            <asp:ControlParameter ControlID="Gridview1" DbType="Int32" Name="CustomerID" PropertyName="SelectedValue" />
        </SelectParameters>
    </asp:ObjectDataSource>

And my method in the entity layer is:

Public Function UpdateCustomerAddressZip(ByVal CustomerID As Integer, ByVal CustomerAddressOne As String, ByVal CustomerZip As Integer)
                Dim dt As New CustomerDataTable
                Dim C_row As CustomerRow = dt.NewCustomerRow

                    C_row.CustomerID = CustomerID
                    C_row.CustomerAddressOne = CustomerAddressOne
                    C_row.CustomerZip = CustomerZip

                Adapter.UpdateCustAddZip(CustomerID, CustomerAddressOne, CustomerZip)
            End Function

With the SQL being

UPDATE Customer
SET CustomerAddressOne = @CustomerAddressOne,
CustomerZip = @CustomerZip
WHERE CustomerID=@CustomerID

Can anyone advise where im going wrong?

Thanks

Was it helpful?

Solution

Simple answer: change OldValuesParameterFormatString="original_{0}" to OldValuesParameterFormatString="{0}"

As you can see from the error:

"ObjectDataSource 'ObjectDataSource1' could not find a non-generic method 'UpdateCustomerAddressZip' that has parameters: CustomerID, CustomerAddressOne, CustomerAddressTwo, CustomerZip, original_CustomerID"

there's an additional parameter: original_CustomerID

That is there in case you want to implement Optimistic Concurrency, to ensure that the Update you are performing on the database don't conflicts with someone else changes.

It is beautifully explained in this tutorial by Scott Mitchell. I report the relevant part here for convenience:

One side effect of using the wizard to configure to ObjectDataSource is that Visual Studio sets the OldValuesParameterFormatString property to original_{0}. This property value is used to include the original values of the data being edited and is useful in two scenarios:

  • If, when editing a record, users are able to change the primary key value. In this case, both the new primary key value and the original primary key value must be provided so that the record with the original primary key value can be found and have its value updated accordingly.

  • When using optimistic concurrency. Optimistic concurrency is a technique to ensure that two simultaneous users don't overwrite one another's changes, and is the topic for a future tutorial.

The OldValuesParameterFormatString property indicates the name of the input parameters in the underlying object's update and delete methods for the original values. We'll discuss this property and its purpose in greater detail when we explore optimistic concurrency. I bring it up now, however, because our BLL's methods do not expect the original values and therefore it's important that we remove this property. Leaving the OldValuesParameterFormatString property set to anything other than the default ({0}) will cause an error when a data Web control attempts to invoke the ObjectDataSource's Update() or Delete() methods because the ObjectDataSource will attempt to pass in both the UpdateParameters or DeleteParameters specified as well as original value parameters.

If this isn't terribly clear at this juncture, don't worry, we'll examine this property and its utility in a future tutorial. For now, just be certain to either remove this property declaration entirely from the declarative syntax or set the value to the default value ({0}).

Note: If you simply clear out the OldValuesParameterFormatString property value from the Properties window in the Design view, the property will still exist in the declarative syntax, but be set to an empty string. This, unfortunately, will still result in the same problem discussed above. Therefore, either remove the property altogether from the declarative syntax or, from the Properties window, set the value to the default, {0}.

BUT, it is also related to the SqlDataSource.ConflictDetection Property

As stated there only when ConflictDetection is set to CompareAllValues the additional parameters should be added to the Update Method call (And the exact name of the parameters for the original values depends on the OldValuesParameterFormatString property.)

By default, the ConflictDetection property is set to OverwriteChanges, which means the data source control will overwrite any changes made to a data row between the time the data source control first read data from the row and the time that the row is updated. The primary key is used for locating the data row that will be updated or deleted, but no other comparison of the data is performed. If the data source control is configured to use the CompareAllValues option, however, the control passes the original data in the oldValues collections of the Update and Delete methods so that you can write logic to update or delete data only if these values match the values currently in the data storage. The matching values indicate that the data has not changed since the time it was read.

So this is not entirely clear to me... It seems that if, as it is by default, the ConflictDetection Property is set to OverwriteChanges, no additional *original_{0}* parameters should be added to the UpdateMethod!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top