2010-12-08 75 views
2

我想要實現:NHibernate Linq .Contains代碼生成有bug?

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

酷,我應該想到這一點,我用** **任何SQL中之前,也許我試圖太多非常的Linq-Y辦法第一和靈感這個http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql,儘可能避免使用lambda和擴展方法。但在這種情況下,任何**看起來比純粹的Linq方法更優雅,並不是所有的SQL概念都可以在Linq語法中捕獲,擴展方法是有保證的**。Distinct()**想到了,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