Entity Framework edit data in grid bound to Entity which uses joins

时间:2016-06-18 20:19:39

标签: c# entity-framework datagridview

I have a DataGridView which binds to a database through Entities (I am using a Database First approach).

I want to display data in a grid (and update this information before posting back to the database) for an Entity which contains Navigation Properties (i.e. Joins).

The context is that there are Permissions in the application; these permissions are separated into relevant sections and every user either has this permission or does not.

The relationships between the tables

The relationships between the tables

In the dialog, there are two grids; one to show the sections available and another to show the permissions within that section and whether the user has that permission enabled; the bottom grid dynamically populates based on the row selected in the top grid.

The DataGridView has AutoGenerateColumns = false and this cannot change (this is because it's a custom DataGridView to which you add columns yourself due to additional properties being required); additionally, the DataPropertyName is set to that of the column I want to display from the appropriate table.

The two approaches I have explored so far are as follows:

  1. Load entire USER_PERMISSIONS entity and bind the DataGridView:

    PermissionsSectionContext.PERMISSIONS_SECTION
        .Load();
    
    PermissionsValues.USER_PERMISSIONS
        .Where(x => x.USER_ID == 5)
        .Load();
    
    SectionsGrid.DataSource = 
        new BindingSource(
            PermissionsSectionContext
            .PERMISSIONS_SECTION.Local.ToBindingList(), null);
    
    ValuesGrid.DataSource =
        new BindingSource(
            PermissionsValues
            .USER_PERMISSIONS.Local
        .Where(x => x.PERMISSIONS_NAME.PERMSECTION_ID == 1), null);
    

Problem: This loads the items fine and I can also edit the permissions values and post this back to the database however the Permissions names (i.e. x.PERMISSIONS_NAME.FRIENDLY_NAME) do not show in the grid:

The Permissions descriptions (i.e. x.PERMISSIONS_NAME.FRIENDLY_NAME) is blank

The DataPropertyName values of the columns in the bottom grid are 'FRIENDLY_NAME' and 'VALUE'.

  1. Creating Anonymous types and then setting the 'Column names' using these anonymous types:

    PermissionsSectionContext.PERMISSIONS_SECTION
        .Load();
    
    PermissionsValues.USER_PERMISSIONS
        .Where(x => x.USER_ID == 5)
        .Load();
    
    SectionsGrid.DataSource = 
        new BindingSource(
            PermissionsSectionContext
            .PERMISSIONS_SECTION.Local.ToBindingList(), null);
    
    ValuesGrid.DataSource =
        new BindingSource(
            PermissionsValues
            .USER_PERMISSIONS.Local
        .Where(x => x.PERMISSIONS_NAME.PERMSECTION_ID == 1), null)
        .Select(x => new {
        FRIENDLY_NAME = x.PERMISSIONS_NAME.FRIENDLY_NAME,
        VALUE = x.VALUE});
    

Problem: All the values show exactly as I want in the grids, including the Permission Name; however, you cannot edit the 'Value' column. Debugging this reveals that when the anonymous type is bound to the DataGridView, it is setting the ReadOnly property to true; this column still needs to be editable and for SaveChanges() to post these changes back, which does work for option (1).

1 个答案:

答案 0 :(得分:0)

感谢Gert Arnold关于使用命名类型的初始响应(非常感谢指针!)我做了一些阅读,我已经设法让它按照我的要求运行。

我做的第一件事是创建一个类,其中只包含我将用作数据操作的一部分的字段:

private class UserPermissionsValue
{
    public int? PERMISSION_ID { get; set; }
    public int? PERMSECTION_ID { get; set; }
    public string FRIENDLY_NAME { get; set; }
    public int? VALUE { get; set; }
}

由于我需要存储适用于用户的所有权限,然后仅在底部网格中显示与顶部网格中所选行相关的权限,因此我保留了对用户的所有权限在List<UserPermissionsValue>

private List<UserPermissionsValue> UserPermissionsList = new List<UserPermissionsValue>();

然后,我可以使用基础实体上的投影来获取此列表所需的记录:

UserPermissionsList = ValuesGrid.DbContext.USER_PERMISSIONS.Local
    .Select(x => new UserPermissionsValue { 
        PERMISSION_ID = x.PERMISSION_ID,
        PERMSECTION_ID = x.PERMISSIONS_NAME.PERMSECTION_ID,
        FRIENDLY_NAME = x.PERMISSIONS_NAME.FRIENDLY_NAME,
        VALUE = x.VALUE
        }
    ).ToList();

使用我设置的现有_RowEnter事件,我只需从我需要的部分中选择权限,然后将其绑定到网格:

int PermissionsSection = ((DataEntity.PERMISSIONS_SECTION)ValuesGrid
    .Rows[e.RowIndex].DataBoundItem).PERMSECTION_ID;

ValuesGrid.DataSource = UserPermissionsList
    .Where(x => x.PERMSECTION_ID == PermSectionID)
    .ToList();

这样做的好处是,在更改顶部网格中的选项时,维护和“记住”修改后的值,因为值和后续更改绑定到UserPermissionsList

最后,在确认对话框时,实际实体被引入并且它们的值被更新为它们在对话框本身中设置的值;我决定在单个请求中恢复所有实体然后在本地迭代实体集合,而不是逐个从数据库中获取记录并以这种方式更新它们,这不会是一个负载:

var PermissionsCommitList = ValuesGrid.DbContext
    .USER_PERMISSIONS.Local;

foreach (DataEntity.USER_PERMISSIONS permission in PermissionsCommitList)
    {
        UserPermissionsValue ValueToCommit = UserPermissionsList
        .Where(x => x.PERMISSION_ID == permission.PERMISSION_ID)
        .First();

        permission.VALUE = ValueToCommit.VALUE;
    }
dtgPermissionsSettings.pFormGrid.DataEntityProvider.SaveChanges();