如何仅从 EF Linq 查询中获取 ID

How to only get the ID from EF Linq query

我正在尝试从 EF linq 查询中获取订单 ID 列表。 sql 查询正在快速返回,但我认为 EF 框架正在尝试创建完整的实体。我只想要订单的 ID。它似乎创建了整个实体,然后将其解析为仅 id。这似乎完全是在浪费资源。

订单是一个包含许多子实体的复杂对象。除了列表中订单的 ID 外,我不需要任何东西。订单被组织成多对多关系的 OrderCollection。

英语中的基本查询是获取指定订单集合中的订单 ID,并使购物车日期比指定日期更新,并且只发送指定页面(跳过并获取)。

示例:

_repo.Orders.Where(o => o.OrderCollection.Any(r => r.Id == RoutingRuleId)).ToList()
                    .Where(o => o.OrderDate >= StartDateTime)
                            .OrderBy(x => x.OrderDate )
                            .Skip(RecordsToSkipCount)
                            .Take(BatchSize).Select(x => new { x.Id }).ToArray();

sql 在调试模式下运行仅需 102 毫秒。但之后我看到内存在失败之前上升到 4GB。 batchsize只有100,好像什么都抢

我尝试移动 select 但也失败了,或者在 运行 和 sql 中出现语法错误或性能不佳(SQL 需要 16 秒)。

例子

    _repo.Orders.Select(x => new { x.Id, x.OrderCollection, x.OrderDate})
                   .Where(o => o.OrderCollection.Any(r => r.Id == RoutingRuleId)).ToList()
                    .Where(o => o.OrderDate >= StartDateTime)
                            .OrderBy(x => x.OrderDate )
                            .Skip(RecordsToSkipCount)
                            .Take(BatchSize).Select(x => new { x.Id }).ToArray();

数据库有数百万条记录。

你所拥有的大概是;

List<Order> list = _repo.Orders
    .Where(o => o.OrderCollection.Any(r => r.Id == RoutingRuleId))
    .ToList();

list.Where(o => o.OrderDate >= StartDateTime)
    .OrderBy(x => x.OrderDate )
    .Skip(RecordsToSkipCount)
    .Take(BatchSize)
    .Select(x => new { x.Id })
    .ToArray();

第一个 .ToList 强制 EF Core 将具有匹配路由规则的每个订单加载到内存中。然后表达式的其余部分使用 IEnumerable 扩展方法来处理这些结果。

我想你想将其重新排列为;

IQueryable<Order> query = _repo.Orders
    .Where(o => o.OrderCollection.Any(r => r.Id == RoutingRuleId)
        && o.OrderDate >= StartDateTime)
    .OrderBy(x => x.OrderDate )
    .Skip(RecordsToSkipCount)
    .Take(BatchSize)
    .Select(x => new { x.Id });

query.ToArray();

创建 IQueryable 不会触发 EF Core 执行任何 SQL。 IQueryable 只是对您想要 运行 的查询的描述。然后是 .ToArray 方法,最终会导致 EF Core 编译并执行一条 sql 语句。