0

我正在尝试编写一个 NHibernate 查询来确定指定的记录是否与请求的来源相关。在这种情况下,指定的记录是客户,如果客户有任何来自指定来源的订单,则该客户是相关的。

我已经尝试过了,但以下查询失败并显示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

将 this 更改为使用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 解决方案。

4

1 回答 1

0

可以通过拆分 Nhibernate 查询来做到这一点,例如

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;
}
于 2012-04-25T10:14:08.543 回答