Michael Buen
Michael Buen

Reputation: 39393

NHibernate Linq .Contains code generation has bug?

I'm trying to achieve:

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

I have this 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 generates this (aliases stripped):

    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 generates the code correctly:

    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 

        )

Is there a problem with subquery code generation on Linq to NHibernate?

However, HQL works:

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

Upvotes: 2

Views: 1028

Answers (2)

Matt Wang
Matt Wang

Reputation: 83

I answered a similar question in this post. Instead of using Contains() operator, we can tweak the subquery a little bit and use Any() operator instead.

LINQ to NHibernate WHERE EXISTS IN

Upvotes: 0

KeithS
KeithS

Reputation: 71573

Certainly looks like a bug, but I think you're overcomplicating the whole query. As I understand, you want all stores where an employee named Steve Jobs is on the payroll. Try:

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

This should generate the query you want, and it's much cleaner and more readable than the subquery.

Upvotes: 6

Related Questions