ObjectDataSource Gridview Insert Fails W/ Empty Va

2019-03-30 10:22发布

问题:

I have a gridview to which I have created an Insert Template in the footer row.

I have an ObjectDataSource which is bound to a business object.

I have an OnInserting event handler which never gets fired.

The program encounters an error once I call .Insert on the ObjectDataSource. The error I receive is that there are no values and that I should check to make sure the values dictionary is not empty.

I do not see a way to insert with a dictionary as a parameter. I have seen mention of grabbing the ObjectDataSourceView and using it's Insert method but I do not see any mention of how to do that and MSDN claims you do not have access.

Is reflection the way to go here? Is there a better way of having an insert row on a gridview? Am I missing something obvious in my steps here?

Below is the code:
ObjectDataSource:

    <asp:ObjectDataSource ID="LeasesDS" runat="server" OnInserting="LeasesDS_Inserting" 
    DataObjectTypeName="CLS.BusObjects.LeaseObj" DeleteMethod="Delete" 
    InsertMethod="Insert" OldValuesParameterFormatString="original_{0}" 
    SelectMethod="GetLeasesByCustomerID" TypeName="CLS.BusObjects.LeaseObj" 
    UpdateMethod="Update">
    <SelectParameters>
        <asp:Parameter Name="customerID" Type="Int32" />
    </SelectParameters>
    <InsertParameters>
        <asp:Parameter Name="CustomerID" Type="Int32" />
        <asp:Parameter Name="PurchaseDate" Type="DateTime" />
        <asp:Parameter Name="AutoYear" Type="Int32" />
        <asp:Parameter Name="Make" Type="String" />
        <asp:Parameter Name="Model" Type="String" />
        <asp:Parameter Name="LeaseEndDate" Type="DateTime" />
    </InsertParameters>
</asp:ObjectDataSource>


CodeBehind Methods:

protected void LeasesGrid_RowCommand(object sender, GridViewCommandEventArgs e)
    {
        if (e.CommandName == "Insert" && Page.IsValid)
        {
            LeasesDS.Insert();
        }
    }
    protected void LeasesDS_Inserting(object sender, ObjectDataSourceMethodEventArgs e)
    {
        DropDownList GridCustomersList = (DropDownList)LeasesGrid.FooterRow.FindControl("GridCustomersList");
        TextBox PurchaseDate = (TextBox)LeasesGrid.FooterRow.FindControl("PurchaseDate");
        TextBox AutoYear = (TextBox)LeasesGrid.FooterRow.FindControl("AutoYear");
        TextBox Make = (TextBox)LeasesGrid.FooterRow.FindControl("Make");
        TextBox Model = (TextBox)LeasesGrid.FooterRow.FindControl("Model");
        TextBox LeaseEndDate = (TextBox)LeasesGrid.FooterRow.FindControl("LeaseEndDate");
        e.InputParameters["CustomerID"] = Convert.ToInt32(GridCustomersList.SelectedValue);
        DateTime? purchaseDate = null;
        if (!string.IsNullOrEmpty(PurchaseDate.Text)) purchaseDate = Convert.ToDateTime(PurchaseDate.Text);
        e.InputParameters["PurchaseDate"] = purchaseDate;
        int? autoYear = null;
        if (!string.IsNullOrEmpty(AutoYear.Text)) autoYear = Convert.ToInt32(AutoYear.Text);
        e.InputParameters["AutoYear"] = autoYear;
        string make = null;
        if (!string.IsNullOrEmpty(Make.Text)) make = Make.Text;
        e.InputParameters["Make"] = make;
        string model = null;
        if (!string.IsNullOrEmpty(Model.Text)) model = Model.Text;
        e.InputParameters["Model"] = model;
        DateTime? leaseEndDate = null;
        if (!string.IsNullOrEmpty(LeaseEndDate.Text)) leaseEndDate = Convert.ToDateTime(LeaseEndDate.Text);
        e.InputParameters["LeaseEndDate"] = leaseEndDate;
    }

回答1:

Your example isn't consistent since you have DataObjectTypeName set, but your LeasesDS_Inserting method is adding parameters as if it's not.

If you don't need DataObjectTypeName, you can remove it and then you should have a better chance getting this to work.

If you need DataObjectTypeName or just prefer it (as I do), there is a way to get this to work, but it's not pretty.

In your LeasesGrid_RowCommand method, you can use code like this to get the view:

IDataSource ds = (IDataSource)LeasesDS;
DataSourceView view = ds.GetView(LeasesGrid.DataMember);

After getting the view, you can build a dictionary containing the values that need to get written to the data object that will eventually get passed in to your Insert method. The code for that will look very similar to what you have in LeasesDS_Inserting, but you'll be inserting into your own dictionary instead of e.InputParameters.

Once you have your dictionary ready, you can invoke Insert on the view with something like this:

view.Insert(dict, delegate { return false; });

That should do it.

You won't need the LeasesDS_Inserting method any more since the view's Insert method will do the work of converting the dictionary you gave it into the data object that it's going to pass in to your Insert method.

If you need to do more processing of the properties on that data object, you will see it in the InputParameters dictionary passed in to LeasesDS_Inserting.