Мне удалось найти два способа сделать это, но не так мало, как Invoke
проб.
0) Некоторый POCO которые я использую для хранения данных
public class AuditReportGroupingDataModelBase
{
public DateTime GroupTime { get; set; }
public int CountryId { get; set; }
}
public class AuditReportGroupingDataModel : AuditReportGroupingDataModelBase
{
public int Count { get; set; }
}
1) Отвратительный путь - с помощью условного оператора в GroupBy
Мое небольшое количество возможностей позволяет трехкомпонентное использование оператора , Однако это не работает должным образом для увеличения количества опций.
var groupedDataQuery = dataQuery
.GroupBy(e => new AuditReportGroupingDataModelBase
{
GroupTime = (filters.TimeSpanId == (int)TimeSpanEnum.Daily ? e.InsertDay : filters.TimeSpanId == (int)TimeSpanEnum.Monthly ? e.InsertMonth : e.InsertDay).Value,
CountryId = e.CountryId.Value
})
.Select(grp => new AuditReportGroupingDataModel
{
GroupTime = grp.Key.GroupTime,
CountryId = grp.Key.CountryId,
Count = grp.Count()
});
Это работает, но порождает уродливые и не очень эффективным заявление SQL:
exec sp_executesql N'SELECT
1 AS [C1],
[GroupBy1].[K2] AS [C2],
[GroupBy1].[K1] AS [CountryId],
[GroupBy1].[A1] AS [C3]
FROM (SELECT
[Filter1].[K1] AS [K1],
[Filter1].[K2] AS [K2],
COUNT([Filter1].[A1]) AS [A1]
FROM (SELECT
[Extent1].[CountryId] AS [K1],
CASE WHEN (1 = @p__linq__0) THEN [Extent1].[InsertDay] WHEN (2 = @p__linq__1) THEN [Extent1].[InsertMonth] ELSE [Extent1].[InsertDay] END AS [K2],
1 AS [A1]
FROM [dbo].[AppEvent] AS [Extent1]
WHERE ([Extent1].[EventTypeId] IN (1)) AND ([Extent1].[CountryId] IS NOT NULL)
) AS [Filter1]
GROUP BY [K1], [K2]
) AS [GroupBy1]',N'@p__linq__0 int,@p__linq__1 int',@p__linq__0=1,@p__linq__1=1
2) лучший способ - выражение GroupBy на основе значения
IQueryable<IGrouping<AuditReportGroupingDataModelBase, AppEvent>> groupedDataQueryInterm = null;
if (filters.TimeSpanId == (int)TimeSpanEnum.Daily) groupedDataQueryInterm = dataQuery.GroupBy(e => new AuditReportGroupingDataModelBase { GroupTime = e.InsertDay.Value, CountryId = e.CountryId.Value });
if (filters.TimeSpanId == (int)TimeSpanEnum.Monthly) groupedDataQueryInterm = dataQuery.GroupBy(e => new AuditReportGroupingDataModelBase { GroupTime = e.InsertMonth.Value, CountryId = e.CountryId.Value });
if (filters.TimeSpanId == (int)TimeSpanEnum.Yearly) groupedDataQueryInterm = dataQuery.GroupBy(e => new AuditReportGroupingDataModelBase { GroupTime = e.InsertYear.Value, CountryId = e.CountryId.Value });
if (groupedDataQueryInterm == null)
throw new InvalidEnumArgumentException([email protected]"Invalid value provided to {nameof(filters.TimeSpanId)}");
var groupedDataQuery = groupedDataQueryInterm
.Select(grp => new AuditReportGroupingDataModel
{
GroupTime = grp.Key.GroupTime,
CountryId = grp.Key.CountryId,
Count = grp.Count()
})
Это создает более SQL:
SELECT
1 AS [C1],
[GroupBy1].[K2] AS [InsertDay],
[GroupBy1].[K1] AS [CountryId],
[GroupBy1].[A1] AS [C2]
FROM (SELECT
[Extent1].[CountryId] AS [K1],
[Extent1].[InsertDay] AS [K2],
COUNT(1) AS [A1]
FROM [dbo].[AppEvent] AS [Extent1]
WHERE ([Extent1].[EventTypeId] IN (1)) AND ([Extent1].[CountryId] IS NOT NULL)
GROUP BY [Extent1].[CountryId], [Extent1].[InsertDay]
) AS [GroupBy1]
Как вы теперь наверняка, LINQ2SQL конвертирует запрос linq в SQL, и я думаю, что вы просто не можете использовать метод invoke. Вы можете просто вызвать вызов перед началом запроса и использовать результат в LINQ2SQL – OrcusZ