【发布时间】:2021-07-29 14:33:03
【问题描述】:
我需要从数据库中获取这个:
- 机架
- 是类型
- 带有所有盒子及其盒子类型的单个货架
- 前一个架子上方的单架子,不带箱子,带架子类型
货架上有VerticalPosition,距离地面几厘米——当我查询时架子上的第二个架子,我需要订购它们并选择索引 1 上的架子。
我现在有这个丑陋的 EF 查询:
var targetShelf = await _warehouseContext.Shelves
.Include(s => s.Rack)
.ThenInclude(r => r.Shelves)
.ThenInclude(s => s.Type)
.Include(s => s.Rack)
.ThenInclude(r => r.Type)
.Include(s => s.Rack)
.ThenInclude(r => r.Shelves)
.Include(s => s.Boxes)
.ThenInclude(b => b.BoxType)
.Where(s => s.Rack.Aisle.Room.Number == targetPosition.Room)
.Where(s => s.Rack.Aisle.Letter == targetPosition.Aisle)
.Where(s => s.Rack.Position == targetPosition.Rack)
.OrderBy(s => s.VerticalPosition)
.Skip(targetPosition.ShelfNumber - 1)
.FirstOrDefaultAsync();
但这会从所有货架上获取所有盒子,并且还会显示警告
Compiling a query which loads related collections for more than one collection navigation, either via 'Include' or through projection, but no 'QuerySplittingBehavior' has been configured. By default, Entity Framework will use 'QuerySplittingBehavior.SingleQuery', which can potentially result in slow query performance.
我也想使用AsNoTracking(),因为我不需要这些数据的更改跟踪器。
第一件事:对于AsNoTracking(),我需要查询Racks,因为它抱怨循环包含。
第二件事:我尝试了这样的条件包含:
.Include(r => r.Shelves)
.ThenInclude(s => s.Boxes.Where(b => b.ShelfId == b.Shelf.Rack.Shelves.OrderBy(sh => sh.VerticalPosition).Skip(shelfNumberFromGround - 1).First().Id))
但这甚至不会转化为 SQL。
我也想到了两个查询——一个是检索带有货架的货架,第二个是箱子,但我仍然想知道是否有一些单一的调用命令。
实体:
public class Rack
{
public Guid Id { get; set; }
public Guid RackTypeId { get; set; }
public RackType Type { get; set; }
public ICollection<Shelf> Shelves { get; set; }
}
public class RackType
{
public Guid Id { get; set; }
public ICollection<Rack> Racks { get; set; }
}
public class Shelf
{
public Guid Id { get; set; }
public Guid ShelfTypeId { get; set; }
public Guid RackId { get; set; }
public int VerticalPosition { get; set; }
public ShelfType Type { get; set; }
public Rack Rack { get; set; }
public ICollection<Box> Boxes { get; set; }
}
public class ShelfType
{
public Guid Id { get; set; }
public ICollection<Shelf> Shelves { get; set; }
}
public class Box
{
public Guid Id { get; set; }
public Guid ShelfId { get; set; }
public Guid BoxTypeId { get; set; }
public BoxType BoxType { get; set; }
public Shelf Shelf { get; set; }
}
public class BoxType
{
public Guid Id { get; set; }
public ICollection<Box> Boxes { get; set; }
}
我希望我解释得足够好。
【问题讨论】:
-
不要尝试在“数据库”查询中做所有事情。使用 c# 加载所需的数据并构建所需的结果。
-
愚蠢的问题 - 为什么不对您列出的这 4 件事进行 4 次查询?
-
我觉得做一个更大的查询比做多个小的查询更好(而且更快?)。我也很好奇 EF 是否(如何)能够处理像这样的复杂查询。
-
有时最好的解决办法是换桌子,给货架一个编号,这样您就不需要按顺序订购了。提高某些条件/查询的性能可能需要您创建数据库函数或过程。
-
第二杰里米的建议;也许您需要离地厘米以进行一些与健康和安全相关的呼叫,但是有一个架子有一个离地的序号位置会使“下一个架子向上”更容易
标签: c# entity-framework entity-framework-core