c# - Linq-to-SQL 谓词 VS UNION
问题描述
我有桌子Order
和OrderItem
。现在,我需要获取一系列订单的所有订单项目(例如,整个月的订单)。订单和订单项目本身有很多列。因此,使用速度非常慢。Include("OrderItem")
订单记录数量约为每月 20K 记录,订单项目约为 50K-60K 记录。
由于目前是一个日期范围(例如,每天、每周、每月、每年等),我正在做 2 次选择。
var orders = (from rec in Orders.AsNoTracking()
where (rec.OrderDate >= startDate) && (rec.OrderDate <= endDate)
orderby rec.OrderDate descending
select rec).ToList();
var orderItems = (from rec in OrderItems.AsNoTracking()
join recOrder in Orders.AsNoTracking() on new { rec.LocationId, rec.StoreId, rec.OrderId } equals new { recOrder.LocationId, recOrder.StoreId, recOrder.OrderId }
orderby recOrder.OrderDate descending
where (recOrder.OrderDate >= startDate) && (recOrder.OrderDate <= endDate)
select rec).ToList();
这一切都很好。但是,当我进行分页时(根据用户偏好,每页可以显示 25 - 1000 条记录),我想摆脱 2 次选择并使用联合或谓词(在 LinqKit 中使用 PredicateBuilder),如下所示:
var orders = (from rec in Orders.AsNoTracking()
where (rec.OrderDate >= startDate) && (rec.OrderDate <= endDate)
orderby rec.OrderDate descending
select rec).Skip(page * recPerPage).Take(recPerPage).ToList();
现在,要获得订单项目,我建议使用 3 个选项。请让我知道哪一个更适合小记录(每页 25 - 1000 条记录)。
选项#1:使用另一个选择与Skip and Take来订购商品。
选项#2:使用联合。
IQueryable<OrderItem> queries = null;
foreach (Tuple<int, int, int> key in orderIds)
{
int locationId = key.Item1, storeId = key.Item2, orderId = key.Item3;
var recs = (from rec in OrderItems.AsNoTracking()
where (rec.LocationId == locationId) && (rec.StoreId == storeId) && (rec.OrderId == orderId)
select rec);
queries = (queries == null) ? recs : queries.Union(recs);
}
var orderItems = queries.ToList();
选项 #3:使用 PredicateBuilder。
var predicate = PredicateBuilder.New<OrderItem>();
foreach (Tuple<int, int, int> key in orderIds)
{
int locationId = key.Item1, storeId = key.Item2, orderId = key.Item3;
predicate = predicate.Or(rec => (rec.LocationId == locationId) && (rec.StoreId == storeId) && (rec.OrderId == orderId));
}
var orderItems = OrderItems.AsNoTracking().AsExpandable().Where(predicate).ToList();
我更喜欢使用Union或PredicateBuilder来获取订单项,该函数不必知道是否使用日期范围或按产品搜索或按客户搜索或任何其他未来搜索选项选择了订单。所有OrderItem需要知道的是订单 ID 列表。
所以,我的问题是,就速度和性能而言,哪个选项是最好的选择?
笔记:
如果我尝试获取 1000 条记录,有时 Union 和 PredicateBuilder 会抛出 StackOverflowException。因此,我将其限制为 500 条记录。如果用户偏好是 1000 条记录,那么,我会打 2 次电话。
我还尝试使用 LINQPad 查看谓词生成器生成的 SQL,但它无法识别
AsExpandable()
(是的,我已包含 LinqKit DLL)。所以,这里没有运气。
请帮忙。
谢谢。
解决方案
推荐阅读
- php - 添加自定义字体 mpdf-laravel
- angular - 来自 chokidar (C:\) 的错误:错误:EBUSY:资源繁忙或锁定,lstat 'C:\DumpStack.log.tmp
- python-3.x - 无法使用python运行while循环遍历csv文件
- c# - ddd 中聚合根模式中具有 Id 的 C# 复合键。为什么?
- javascript - 为什么 queryselectorAll 不能用于删除元素?
- r - 你如何用另一列的条件值填充一列?
- sql-server-data-tools - 如何在 t4 脚本中处理 varchar(max)?
- php - 如何在视图中渲染上传的图像?
- javascript - 由粒子滑块组成的背景由于其上的其他 div 而没有触发
- javascript - 尝试使用 js 和 Imgur API 发布图像时出现 CORS 错误