GridView with ObjectDatasource UpdateMethod

2019-05-17 16:40发布

问题:

I have an ASP.NET WebForms page containing an ASPxGridView and an ObjectDataSource:

<dx:ASPxGridView ID="gvEmployees" runat="server"
    AutoGenerateColumns="False" DataSourceID="objDsEmployees"
    KeyFieldName="EmployeeId">
    <Columns>
        <dx:GridViewCommandColumn VisibleIndex="0">
            <EditButton Visible="True" />
        </dx:GridViewCommandColumn>
        <dx:GridViewDataTextColumn FieldName="EmployeeId" VisibleIndex="1" />
        <dx:GridViewDataTextColumn FieldName="Name" VisibleIndex="2" />
        <dx:GridViewDataTextColumn FieldName="Email" VisibleIndex="3" />
        <dx:GridViewDataTextColumn FieldName="Telephone" VisibleIndex="5" />
    </Columns>
</dx:ASPxGridView>
<asp:ObjectDataSource ID="objDsEmployees"
    runat="server"
    ConflictDetection="CompareAllValues"
    DataObjectTypeName="MySite.Data.Models.Employee"
    DeleteMethod="Delete"
    OldValuesParameterFormatString="original{0}"
    InsertMethod="Insert"
    SelectMethod="GetAll"
    TypeName="MySite.Services.EmployeeService"
    UpdateMethod="Update" />

The Employee model contains the following properties:

public class Employee
{
    public int EmployeeId { get; set; }

    public string Name { get; set; }

    public string Email { get;

    public string Password { get; set; }

    public string Telephone { get; set; }
}

The ObjectDataSource calls the Update method in the service layer:

public void Update(Employee employee, Employee originalEmployee)
{
    _db.Employees.Attach(originalEmployee);
    _db.Entry(originalEmployee).CurrentValues.SetValues(employee);
    _db.SaveChanges();
}

When the Update method is called, the parameters employee and originalEmployee only contain the properties used as columns in the ASPxGridView and the other properties (Password for example) are null.

Is there a way I can preserve these values somewhere? By the way, I use Entity Framework for data access and DevExpress for the GridView.

回答1:

You can also solve this by setting ConflictDetection="CompareAllValues" in the ObjectDataSource:

<asp:ObjectDataSource ID="objDsEmployees"
    runat="server"
    DeleteMethod="Delete"
    InsertMethod="Insert"
    SelectMethod="GetAll"
    UpdateMethod="Update"
    DataObjectTypeName="App.Core.Domain.Employee"
    TypeName="App.Core.Services.EmployeeService"
    OldValuesParameterFormatString="original{0}"
    ConflictDetection="CompareAllValues" />

Then in the Update method in EmployeeService we fetch the original employee first by its id, then we merge this original employee with the updated employee. This makes sure that not updated properties don't become null - although it requires an extra call to the database:

public void Update(Employee originalEmployee, Employee employee)
{
    // Get the original employee by its id.
    Employee fullOriginalEmployee = GetById(originalEmployee.EmployeeId);

    // Merge the data of the updated employee with the original employee.
    fullOriginalEmployee.Name = employee.Name;
    fullOriginalEmployee.Email = employee.Email;
    fullOriginalEmployee.Telephone = employee.Telephone;
    fullOriginalEmployee.BirthDate = employee.BirthDate;

    // Persist changes in database.
    SaveChanges();
}


回答2:

I solved this by changing the ObjectDataSource to:

<asp:ObjectDataSource 
    ID="objDsEmployees"
    runat="server"
    DeleteMethod="Delete"
    InsertMethod="Insert"
    SelectMethod="GetAll"
    TypeName="MySite.Services.EmployeeService"
    UpdateMethod="Update">
    <UpdateParameters>
        <asp:Parameter Name="employeeId" Type="Int32" />
        <asp:Parameter Name="name" Type="String" />
        <asp:Parameter Name="email" Type="String" />
    </UpdateParameters>
</asp:ObjectDataSource>

And the Update method in the service layer to:

public void Update(int employeeId, string name, string email)
{
    var employee = GetById(employeeId);
    employee.Name = name;
    employee.Email = email;

    _db.SaveChanges();
}

Other solutions are, however, more than welcome!