我正在尝试将以下SQL转换为EF Core查询,并且收到警告,即将在本地评估GroupBy和Sum。无论如何,当前是否有写它可以完全转换为SQL的方法?
SELECT UserId, ST.StatusId, SUM(DATEDIFF(MINUTE, StartDate, ISNULL(EndDate,GETDATE()))) AS Time
FROM StatusTransaction ST
WHERE
TeamManagerId = 1
AND StartDate >= N'01-01-2019'
AND ISNULL(EndDate,GETDATE()) <= N'01-02-2019'
GROUP BY UserId, ST.StatusId
ORDER BY UserId
这些是我使用过的EF查询:
var efFunction = await context
.Where(st => st.TeamManagerId == tmId && st.StartDate >= dateFrom && (st.EndDate ?? DateTime.Now) <= dateTo)
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => Microsoft.EntityFrameworkCore.EF.Functions.DateDiffMinute(st.StartDate, st.EndDate)) // null check not done on end date - (st.EndDate ?? DateTime.Now) causes an error here
}).ToListAsync(cancellationToken).ConfigureAwait(false);
var simpleDateSubtraction = await context
.Where(st => st.TeamManagerId == tmId && st.StartDate >= dateFrom && (st.EndDate ?? DateTime.Now) <= dateTo)
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.EndDate.Value.Subtract(st.StartDate).Minutes)// null check not done on end date - (st.EndDate ?? DateTime.Now) causes an error here
}).ToListAsync(cancellationToken).ConfigureAwait(false);
var groupBySimpleSum = await context
.Where(st => st.TeamManagerId == tmId)
.GroupBy(st => new { st.TeamManagerId, st.OperationsManagerId })
.Select(g => new
{
g.Key.OperationsManagerId,
g.Key.TeamManagerId,
Foo = g.Sum(st => st.UserId) // nonsense but a simple column to sum, this translates fully to SQL
}).ToListAsync(cancellationToken).ConfigureAwait(false);
答案 0 :(得分:4)
首先,EF Core仍然不支持翻译TimeSpan
操作,并且DateTime
的差异会产生TimeSpan
,因此EF.Functions.DateDiff
方法是正确的方法。
第二,它仍然只能在简单的成员访问器表达式上转换GroupBy
聚合。因此,您必须预先Select
GroupBy
表达式:
var query = context
.Where(st => st.TeamManagerId == tmId
&& st.StartDate >= dateFrom
&& (st.EndDate ?? DateTime.Now) <= dateTo
)
.Select(st => new
{
st.UserId,
st.StatusId,
Time = EF.Functions.DateDiffMinute(st.StartDate, st.EndDate ?? DateTime.Now)
})
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.Time)
});
或使用GroupBy
重载允许预先选择聚集的来源:
var query = context
.Where(st => st.TeamManagerId == tmId
&& st.StartDate >= dateFrom
&& (st.EndDate ?? DateTime.Now) <= dateTo
)
.GroupBy(st => new { st.UserId, st.StatusId }, st => new
{
Time = EF.Functions.DateDiffMinute(st.StartDate, st.EndDate ?? DateTime.Now)
})
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.Time)
});