2010-06-08 2 views
2

У меня есть следующий Дозвуковой 3.0 запрос, который содержит вложенную NotIn запрос:Subsonic 3 ActiveRecord вложенный выбор для ошибки NotIn?

public List<Order> GetRandomOrdersForNoReason(int shopId, int typeId) 
{ 
    // build query  
    var q = new SubSonic.Query.Select().Top("1") 
     .From("Order") 
     .Where("ShopId") 
     .IsEqualTo(shopId) 
     .And(OrderTable.CustomerId).NotIn(
      new Subsonic.Query.Select("CustomerId") 
       .From("Customer") 
       .Where("TypeId") 
       .IsNotEqualTo(typeId)) 
      .OrderDesc("NewId()"); 

    // Output query 
    Debug.WriteLine(q.ToString()); 

    // returned typed list 
    return q.ExecuteTypedList<Order>(); 
} 

Внутренний запрос представляется неверным:

SELECT TOP 1 * 
FROM [Order] 
WHERE ShopId = @0 AND CustomerId NOT IN (SELECT CustomerId 
FROM [Customer] 
WHERE TypeId = @0) 
ORDER BY NewId() ASC 

Вы заметите, что оба параметра @ 0. Я предполагаю, что параметры перечислены (начиная с нуля), для каждого «нового» запроса Select. Однако в этом случае, когда два запроса выбора являются вложенными, я ожидал, что на выходе будут два параметра: @ 0 и @ 1.

Мой запрос основан на one, что Роб Конери дал в своем блоге, как предварительный просмотр «Pakala» инструмент запроса, который стал Дозвуковые 3. Его пример был:

int records = new Select(Northwind.Product.Schema) 
    .Where("productid") 
    .In(
     new Select("productid").From(Northwind.Product.Schema) 
     .Where("categoryid").IsEqualTo(5) 
     ) 
    .GetRecordCount(); 

Кто-нибудь еще видел такое поведение? Это ошибка, или это ошибка или моя роль? Поскольку я новичок в Subsonic, я предполагаю, что это, вероятно, ошибка программиста с моей стороны, но я бы хотел, если возможно, подтверждение.

ответ

1

Только что натолкнулся на эту ту же самую проблему в последней версии, поэтому, по-видимому, она еще не исправлена. Я попытался переключить порядок условий (сначала установив условие NotIn), и это сделало трюк. Вот как выглядит новый код, который создает параметры @ 0 и @ 1 вместо @ 0 и @ 0:

var q = new SubSonic.Query.Select().Top("1") 
    .From("Order") 
    .Where(OrderTable.CustomerId).NotIn(
     new Subsonic.Query.Select("CustomerId") 
      .From("Customer") 
      .Where("TypeId") 
      .IsNotEqualTo(typeId) 
    ) 
    .And("ShopId") 
    .IsEqualTo(shopId) 
    .OrderDesc("NewId()"); 
1

Я не уверен в SubSonic 3, но в SubSonic 2, если вы запустите этот код, внутренний запрос будет выполнен первым, а второй запрос будет иметь теги категорий, которые уже определены как параметр в запросе.
Возможно, это ошибка, и вы должны опубликовать ее на github.

В любом случае вы могли бы сделать вашу работу запроса на данный момент, и вести себя как дозвуковые 2 подчиненного запроса с этим небольшим изменением:

var q = new SubSonic.Query.Select().Top("1") 
    .From("Order") 
    .Where("ShopId") 
    .IsEqualTo(shopId) 
    .And(OrderTable.CustomerId).NotIn(
     new Subsonic.Query.Select("CustomerId") 
      .From("Customer") 
      .Where("TypeId") 
      .IsNotEqualTo(typeId) 
      .ExecuteTypedList<int>() 
    ) 
    .OrderDesc("NewId()"); 

NotIn должен принять IEnumerable в качестве параметра, но д будет содержать весь список CustomerIds как параметр перед выполнением внешней части.

Не настоящее решение, но быстрое решение на данный момент (если оно не сильно влияет на производительность).

Смежные вопросы