我有这个函数返回一个IQueryable:
private IQueryable<string> GetActiveCellPhoneNumbersUpToDate(long serviceToken, DateTime date, bool? isPrepaid = null)
{
var to = date.AddDays(1).Date;
var query = ViewRepository
.All
.Where(i => i.ServiceToken == serviceToken)
.Where(i => i.Date < to);
if (isPrepaid.HasValue)
{
query = query.Where(i => i.IsPrepaid == isPrepaid);
}
query = query.OrderByDescending(i => i.Date);
var result = query
.GroupBy(i => i.CellPhoneNumber)
.Where(i => i.First().ActionId == (int)SubscriptionAction.Subscription)
.SelectMany(i => i.ToList())
.Select(i => i.CellPhoneNumber)
.Distinct();
return result;
}
并且此函数将被称为另一个仅用于计数的函数:
var prepaidsCount = GetActiveCellPhoneNumbersUpToDate(serviceToken, DateTime.Date, true);
var postPaidsCount = GetActiveCellPhoneNumbersUpToDate(serviceToken, DateTime.Date, false);
当我执行它时,我看到EF 3.0 发生了重大变化,上面写着:
'NavigationExpandingExpressionVisitor' 处理 LINQ 表达式 'i => i .ToList()' 失败。这可能表示 EF Core 中的错误或限制。有关更多详细信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2101433。
如重大更改说明中所述,我需要使用复杂子句AsEnumerable或ToList在复杂Where子句之前执行该部分 LINQ 并将数据带入 RAM,然后继续我的查询。
但是对于需要动态查询的大量数据,这绝对是疯狂的,而且效率低得难以想象。
这个有什么替代品?我们如何创建动态复杂查询以在运行时进行翻译并且只返回一个奇异的标量值?
更新:现实世界的需求不是 hello-world 的例子。它们需要将复杂的过滤、排序和分组等功能混合在一起,从关系结构中提取数据。过去,我们会为此目的使用存储过程。将几个参数传递给数据库,并编写丑陋的、难以测试的、难以维护的、每周键入的、抗重构的 SQL 代码来获取数据。
现在我想到的唯一选择是降级回那些丑陋的存储过程。这个噩梦在 EF 3.1 中是否成为现实?
更新 2:这是我的场景。我有一张表,其中存储了特定服务中的手机号码订阅/取消。该表的简化版本为:
create table Subscriptions
(
Id,
CellPhoneNumber,
ServiceId,
Date,
ActionId
)
这些可以是记录:
John,+1-541-754-3010,15,2019-10-13 12:10:06.153,1
John,+1-541-754-3010,15,2019-10-18 12:10:06.153,2
在这里我们可以看到 John 订阅了服务 15,并在其中停留了 5 天,然后他取消了。如果我们想报告2019-10-14有多少订阅者,John 将被计算在内。因为那个时候,他最后的动作就是报名。但是,如果我们想报告我们有多少订阅者,2910-11-03那么 John 的最后一个动作是离开服务,他不应该被计算在内。