如何在复杂的计算数据基础上正确地执行带有子句的LINQ查询
本文关键字:执行 行带 子句 查询 LINQ 正确地 基础上 复杂 计算 数据 | 更新日期: 2023-09-27 18:01:19
我对LINQ to Entities和LINQ to SQL有相当丰富的经验,但是这个查询让我头疼。
我需要一些指导如何成功地创建一个干净的LINQ到实体查询,当它有基于计算列的条件子句,当将数据投影到对象时,也要使用计算列。
投影结果类如下:
public class FilterClientsResult
{
public enum ClientType
{
ALL,
LIST,
VIP
}
public int ClientId { get; set; }
public string Document { get; set; }
public string Email { get; set; }
public string LastName { get; set; }
public string Name { get; set; }
public ClientType Type { get; set; }
public int Visits { get; set; }
}
那么数据来自一个主要来源和三个补充来源。
主要来源是Client实体,在其所有属性中,它具有所有预测属性,除了最后两个(类型和访问)
其他来源是:
Subscription
,其中一个Client
可以有多个Subscription
。
ClientAccess
,其中1个Subscription
可以有多个ClientAccess
。
GuestListClient
,其中一个Client
可以有多个GuestListClient
。
因此,当Client
同时与ClientAccess
和GuestListClient
实体相关时,ClientType Type
属性被设置为FilterClientsResult.ClientType.ALL
。
当Client
只与ClientAccess
实体相关时设置为FilterClientsResult.ClientType.VIP
,当Client
只与GuestListClient
实体相关时设置为FilterClientsResult.ClientType.LIST
。
则设置Visits
属性为Client
所关联的ClientAccess
和GuestListClient
实体之和。
所以我需要的查询应该能够通过FilterClientsResult.ClientType
过滤客户端,但也预测FilterClientsResult.ClientType
。
我还需要通过Visits
范围进行过滤,但也要投影Visits
值。
使用let
关键字将中间结果存储为变量,这在查询语法中效果最好:
from c in Clients
let vipCount = c.Subscriptions.SelectMany(s => s.ClientAccesses).Count()
let listCount = c.GuestListClients.Count()
select new FilterClientsResult {
c.ClientId,
...
Type = vipCount > 0 ? listCount > 0 ? ClientType.ALL
: ClientType.VIP
: listCount == 0 ? 0
: ClientType.LIST,
Visits = vipCount + listCount
}
(未检查语法)
注意ClientType
enum必须为EF所知,否则您首先必须投影所需的属性,其中Type
是int
。然后,在AsEnumerable()
之后,将int类型强制转换为enum类型。
还要注意,当两个计数都为0时,存在一个不确定的值。