我正在尝试编写一个NHibernate Query,它确定指定的记录是否与请求的来源相关。在这种情况下,指定的记录是客户,如果客户有来自指定来源的任何订单,则客户是相关的。
我已经开始了,但是以下查询失败了QuerySyntaxException
。
bool IsRelevant = Session.Query<Order>().Where
(
ThisOrder => ThisOrder.Customer.ID == ThisCustomer.ID
&&
ThisOrder.Items.OfType<SourceOrderItem>().Where
(
I => I.Source.ID == Source.ID
).Count() > 0
).Count() > 0;
我认为问题的至少一部分是SourceOrderItem
是OrderItem
的子类型,并且订单可能包含不属于该类型的项目,因此查询只需要进行额外的过滤查看正确类型的项目。
例外:
Exception of type 'Antlr.Runtime.NoViableAltException' was thrown. [.Count[Domain.Order](.Where[Domain.Order](NHibernate.Linq.NhQueryable`1[Domain.Order], Quote((R, ) => (AndAlso(Equal(R.Customer.ID, p1), GreaterThan(.Count[Domain.SourceOrderItem](.Where[Domain.SourceOrderItem](.OfType[Domain.SourceOrderItem](R.Items, ), (I, ) => (Equal(I.Source.ID, p2)), ), ), p3)))), ), )]
使用Nhibernate版本3.1.0.4000
将此更改为使用Any
而不是Where().Count > 0
会导致尝试运行查询的SQL异常
DECLARE @p0 int
DECLARE @p1 int
DECLARE @p2 int
SET @p0 = 1
SET @p1 = 1
SET @p2 = 1
select TOP (@p0)
request0_.ID as ID24_,
request0_.Date as Date24_,
request0_.Delivery as Delivery24_,
request0_.PO as PO24_,
request0_.Discount as Discount24_,
request0_.Notes as Notes24_,
request0_.PaymentType as PaymentT7_24_,
request0_.Transport as Transport24_,
request0_.Customer_id as Customer9_24_,
request0_.Site_id as Site10_24_,
request0_.CreatedBy_id as CreatedBy11_24_,
request0_1_.OrderNumber as OrderNum2_25_,
request0_2_.Revision as Revision26_,
request0_2_.ExpiryDate as ExpiryDate26_,
case
when request0_1_.Request_id is not null then 1
when request0_2_.Request_id is not null then 2
when request0_.ID is not null then 0
end as clazz_
from [Request] request0_
left outer join [Order] request0_1_ on request0_.ID=request0_1_.Request_id
left outer join [Quote] request0_2_ on request0_.ID=request0_2_.Request_id
where
request0_.Site_id=@p1
and
(exists
(select
items1_.ID
from
[RequestItem] items1_
where request0_.ID=items1_.Request_id
and case
when items1_2_.ChargeableRequestItem_id is not null then 2
when items1_3_.ChargeableRequestItem_id is not null then 3
when items1_1_.RequestItem_id is not null then 1
when items1_4_.RequestItem_id is not null then 4
when items1_.ID is not null then 0
end=3
and items1_3_.Source_id=@p2))
这似乎在语句中缺少了很多,因为没有声明第二个case语句下面的表。
现在我通过自己编写SQL来解决这个问题。
bool IsRelevant = ((Int32)Session.CreateSQLQuery(
"Select COUNT(*) as IsRelevant From Request\r\n" +
"Where\r\n" +
" Request.Site_Id = :p0\r\n" +
" And Request.ID in \r\n" +
"(\r\n" +
"Select Request_ID From RequestItem Where ID in\r\n" +
" ( \r\n" +
" Select SourceOrderItem.ChargeableRequestItem_id\r\n" +
" From SourceOrderItem\r\n" +
" Where SourceOrderItem.Source_id = :p1\r\n" +
" )\r\n" +
")"
).SetParameter("p0", S.ID).SetParameter("p1", Source.ID).UniqueResult()) > 0;
虽然我仍然喜欢NHibernate解决方案。
答案 0 :(得分:0)
可以通过拆分Nhibernate查询来完成此操作 e.g。
var Items = Session.Query<SourceOrderItem>().Where(I=> I.Source.ID == Source.ID).ToList();
foreach(var Item in Items)
{
IsRelevant = Session.Query<Order>().Any(R => R.Customer.ID == C.ID && R.Items.Any(I => I.ID == Item.ID));
if (IsRelevant)
break;
}