2010-12-08 4 views
2

Я пытаюсь добиться:NHibernate Linq. У кода генерации кода есть ошибка?

select StoreId, StoreName from Store where StoreId in (
    select StoreId from Employee where EmployeeName = 'Steve Jobs') 

У меня есть этот код:

public class Store 
{ 
    public virtual int StoreId { get; private set; } 
    public virtual string StoreName { get; set; } 

    public virtual IList<Employee> Staff { get; set; } 
} 

public class Employee 
{ 
    public virtual Store Store { get; set; } 

    public virtual int EmployeeId { get; private set; } 
    public virtual string EmployeeName { get; set; } 
} 



var q = from s in session.Query<Store>() 
     where 
      (from e in session.Query<Employee>() 
      where s.EmployeeName == "Steve Jobs" 
      select e.Store.StoreId).Contains(s.StoreId) 
     select s; 

NHibernate генерирует это (псевдонимы раздели):

select s.StoreId, s.StoreName 
    from Store s 
    where exists 
     (
      select t.StoreId 
      from Employee e 
      left join Store t on t.StoreId = e.StoreId 
      where e.EmployeeName = 'Steve Jobs' 

       -- wrongly generated code 
       and t.EmployeeId = s.StoreId 

     ) 

Linq-toSql генерирует код правильно :

select s.StoreId, s.StoreName 
    from Store s 
    where exists 
     (
      select null 
      from Employee e 
      where e.EmployeeName = 'Steve Jobs'       
       and e.StoreId = s.StoreId 

     ) 

Есть ли проблема с генерацией кода подзапроса в Linq для NHibernate?

Однако HQL работы:

var q = session.CreateQuery("from Store as s where s.StoreId in (select e.WorkingInStore.StoreId from Employee as e where e.EmployeeName = 'lennon')").List<Store>(); 

ответ

6

Конечно выглядит как ошибка, но я думаю, что вы усложнять весь запрос. Насколько я понимаю, вы хотите, чтобы все магазины, где сотрудник по имени Стив Джобс был начислением заработной платы. Попробуйте:

var q = from s in session.Query<Store>() 
     where s.Staff.Any(e=>e.EmployeeName == "Steve Jobs") 

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

+0

Круто, я бы подумал о том, что я использовал ** ANY ** в SQL раньше, или, может быть, я пытаюсь это слишком много в очень Linq-у подхода первой и вдохновленный этот http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql, избегая при этом методов лямбда и расширения, если это вообще возможно. Но в этом случае ** Любое ** выглядит более элегантно, чем чистый подход Linq, и не вся концепция SQL может быть захвачена в синтаксисе Linq, метод расширения оправдан, **. Особый() ** приходит на ум, http: //www.ienablemuch.com/2010/12/performing-order-by-on-distinct-on-linq.html – 2010-12-08 23:30:40

0

Я ответил на аналогичный вопрос в этом посте. Вместо использования оператора Contains() мы можем немного подстроить подзапрос и использовать вместо него оператор Any().

LINQ to NHibernate WHERE EXISTS IN

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