Как исправить ядро ​​Entity Framework «Типы аргументов не совпадают» с проекцией Linq Select - PullRequest
1 голос
/ 09 мая 2019

При попытке прямого проецирования с использованием Entity Framework Core и Linq я получаю исключение "Типы аргументов не совпадают".

Я рассмотрел возможные причины и сузил его до Select это вызывает ошибку (см. ниже).Существует проблема GitHub , описывающая аналогичную ситуацию с простыми типами и необязательными элементами навигации, но ни одно из предложенных решений не помогло мне.Это не тип nullable, и я пробовал приводить или использовать Value для любых дочерних свойств.Я также попытался установить отношение к требуемому в DbContext, что не совсем идеально.

Вот запрос Linq в хранилище:

return await _dashboardContext.PresetDashboardConfig
    .Where(config => config.DashboardTypeId == dashboardType && config.OrganisationType = organisationType)
    .GroupBy(config => config.GroupId)
    .Select(config => new DashboardConfigDTO
    {
        DashboardType = config.First().DashboardTypeId,
        OrganisationId = organisationId,
        WidgetGroups = config.Select(group => new WidgetGroupDTO
        {
            Id = group.Id,
            Name = group.GroupName,
            TabOrder = group.TabOrder,

            // Problem Select below:
            Widgets = group.Widgets.Select(widget => new WidgetConfigDTO
            {
                IndicatorId = widget.IndicatorId,
                ScopeId = widget.ScopeId.ToString(),
                ParentScopeId = widget.ParentScopeId.ToString(),
                WidgetType = widget.WidgetType,
                WidgetSize = widget.WidgetSize,
                Order = widget.Order
            })
        })
    })
    .SingleOrDefaultAsync();

И сущности:

public class DashboardConfig
{
    public int Id { get; set; }
    public int DashboardTypeId { get; set; }
    public int OrganisationType {get; set; }
    public int GroupId { get; set; }
    public string GroupName { get; set; }
    public int TabOrder { get; set; }
}

public class PresetDashboardConfig : DashboardConfig
{
    public ICollection<PresetWidgetConfig> Widgets { get; set; }
}

public class WidgetConfig
{
    public int Id { get; set; }
    public int IndicatorId { get; set; }
    public long ScopeId { get; set; }
    public long? ParentScopeId { get; set; }
    public int WidgetType { get; set; }
    public int WidgetSize { get; set; }
    public int Order { get; set; }
}

public class PresetWidgetConfig : WidgetConfig
{
    public int PresetDashboardConfigId { get; set; }
}

И, наконец, DbContext ModelBuilder:

modelBuilder.Entity<PresetDashboardConfig>(entity =>
{
    entity.Property(e => e.GroupName)
        .HasMaxLength(32)
        .IsUnicode(false);

    entity.HasMany(e => e.Widgets)
        .WithOne();
});

Ниже приведены классы DTO согласно комментарию Хенка:

public class DashboardConfigDTO
{
    public int DashboardType { get; set; }
    public int OrganisationId { get; set; }
    public IEnumerable<WidgetGroupDTO> WidgetGroups { get; set; }
}

public class WidgetGroupDTO
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int TabOrder { get; set; }
    public IEnumerable<WidgetConfigDTO> Widgets { get; set; }
}

public class WidgetConfigDTO
{
    public int IndicatorId { get; set; }
    public string ScopeId { get; set; }
    public string ParentScopeId { get; set; }
    public int WidgetType { get; set; }
    public int WidgetSize { get; set; }
    public int Order { get; set; }
}
...