我有一个包含Item,Tax,TaxItem和ItemPrice表的数据库。除ItemPrice表外,这些关系都非常简单。在ItemPrice表中,给定ItemId可以有多行,因为Locations可以覆盖Region级别指定的价格。每条记录必须包含RegionId或LocationId,但不能同时包含两者,并且都不能为null。
ItemPrice
ID
ItemId
LocationId(可为空)
价格
RegionId(可为空)
项目
ID
名称
税收
ID
名称
类型
值
TaxItem
ItemId
TaxId
我正在使用的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
我在ItemPrice表中有两个ID为1的记录。
LocationId Price RegionId 1 1.25 NULL NULL 1.50 1
如何获取Lambda表达式以将子查询限制为第一行?
答案 0 :(得分:0)
那么您无需使用GetAllInclusion方法,因为它看起来包括整个集合...
答案 1 :(得分:0)
我认为Abion47的评论是关于金钱的,但是我通过升级到EF Core 2.1.1并使用Query HTTP
var taxInfo = Context.Query<TaxItemInfo>().FromSql
(
$@"select ti.TaxId, ti.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"
);
答案 2 :(得分:0)
我不是ABP框架,这是普通的Linq:
var taxItems = from ti in context.TaxItem
let ip = ti.Item.ItemPrice
.FirstOrDefault(x => x.LocationId == LocationId ||
x.RegionId == locationCacheItem.RegionId)
select new {
TaxId = ti.TaxId,
ApplyTax = ti.ApplyTax,
Price = ip.Price,
TaxValue = ti.Tax.Value,
SpecifyItems = ti.Tax.SpecifyItems,
TaxType = ti.Tax.TaxType,
UseNetPrice = ti.Tax.UseNetPrice
};