2010-12-08 7 views
2

Ich versuche zu erreichen:NHibernate Linq .Contains Code-Generierung hat Fehler?

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

Ich habe diesen Code:

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 generiert diese (Aliase gestrippt): richtig

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 generiert den Code :

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 

     ) 

Gibt es ein Problem mit der Generierung von Unterabfragen unter Linq zu NHibernate?

jedoch HQL funktioniert:

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>(); 

Antwort

6

sieht auf jeden Fall wie ein Fehler, aber ich denke, Sie die ganze Abfrage sind overcomplicating. Soweit ich weiß, möchten Sie alle Geschäfte, in denen ein Mitarbeiter namens Steve Jobs auf der Gehaltsliste steht. Versuchen Sie:

Dies sollte die Abfrage generieren, die Sie wollen, und es ist viel sauberer und lesbarer als die Unterabfrage.

+0

Cool, sollte ich das gedacht, ich ** ** ANY in SQL vor verwendet haben, oder vielleicht in einem sehr Linq-y Ansatz ersten und inspiriert sie zu viel Ich bin versucht, durch dies http://blog.wekeroad.com/2008/02/27/creating-in-quiries-with-linq-to-sql, Vermeidung von Lambda und Erweiterung Methoden, wenn überhaupt möglich. Aber in diesem Fall, **. Any ** sieht eleganter als reine Linq Ansatz, und nicht alle SQL-Konzept kann in Linq-Syntax erfasst werden, Erweiterung Methode ist gerechtfertigt, **. Distinct() ** kommt in den Sinn, http: //www.ienablemuch.com/2010/12/performing-order-by-on-distinct-on-linq.html –

+0

Ich hoffe jedoch, dass Linq NHibernate Team den Fehler beheben wird. Linq Verkettung ist nicht nur ordentlich, es fördert die Wiederverwendung von Code zu http://blog.wekeroad.com/2008/02/27/creating-in-quiries-with-linq-to-sql –

0

Ich beantwortete eine ähnliche Frage in diesem Post. Anstatt den Operator Contains() zu verwenden, können wir die Unterabfrage etwas optimieren und stattdessen den Operator Any() verwenden.

LINQ to NHibernate WHERE EXISTS IN