【发布时间】:2018-08-08 23:04:22
【问题描述】:
我有一个包含 Item、Tax、TaxItem 和 ItemPrice 表的数据库。除了 ItemPrice 表之外,这些关系非常简单。在 ItemPrice 表中,给定的 ItemId 可以有多行,因为 Locations 可以覆盖在区域级别指定的价格。每条记录必须包含 RegionId 或 LocationId 但不能同时包含两者,并且两者都不能为空。
商品价格
身份证
物品编号
LocationId(可为空)
价格
RegionId(可为空)
项目
身份证
姓名
税收
身份证
名称
类型
价值
税项
物品编号
税号
我使用的 ABP 框架利用了存储库模式。我目前的代码如下:
var taxItems = _TaxItemRepository
.GetAllIncluding(ti => ti.Item, ti => ti.Tax, ti => ti.Item.ItemPrice)
.Where(ti =>
(ti.ItemId == ItemId)
&&
(
(ti.Item.ItemPrice.LocationId.HasValue && ti.Item.ItemPrice.LocationId == LocationId)
||
(!ti.Item.ItemPrice.LocationId.HasValue && ti.Item.ItemPrice.RegionId == locationCacheItem.RegionId)
)
);
很遗憾,它不等同于以下提供正确结果的 SQL:
declare @ItemId bigint, @LocationId bigint, @RegionId bigint
set @ItemId = 1
set @LocationId = 1
set @RegionId = 1
select ti.TaxId as TaxId, ti.ApplyTax as ApplyTax, ip.Price, tx.Value as TaxValue, tx.SpecifyItems, tx.TaxType, tx.UseNetPrice
from TaxItem ti
inner join Tax tx on tx.id = ti.TaxId
inner join Item on ti.ItemId = Item.Id
inner join
(
select top 1 locationId, regionId, ItemId, Price
from ItemPrice
where ItemId = @ItemId and
(
(LocationId is not null and LocationId = @locationId) OR
(LocationId is null and RegionId = @RegionId)
)
) ip on ip.ItemId = Item.Id
ItemID 1 的 ItemPrice 表中有两条记录:
LocationId 价格 RegionId 1 1.25 空 空 1.50 1如何获取 Lambda 表达式以将子查询限制在第一行?
【问题讨论】:
-
您是否尝试过使用
.First()? -
是的。它将主要结果集限制为第一行,而不是子查询
-
SQL版本子查询中有“select Top 1”
-
那么最明智的方法可能是将 C# 版本拆分为两个查询 - 首先执行“子查询”,将
.First()的结果存储在一个临时变量中,然后在“主要”查询。 -
只是一个小连接点:如果没有排序顺序,“第一”行的概念是危险的。在某些情况下(创建日期、ID 等)对人类来说可能是显而易见的,但是,您不应该依赖默认返回的顺序,因为它不能保证是确定性的。