Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to NHibernate, "get by array of ids" query

Code:

 public IList<T> GetByMultipleIds(int[] ids)
 {
        List<T> result =
            _session.Linq<T>()
                .Where(x => ids.Contains(x.Id)).ToList();

        return result;
 }

Throws:

An exception of type 'System.NullReferenceException' occurred in 
NHibernate.DLL but was not handled in user code

Additional information: Object reference not set to an instance of an object.

ids={1}; T is typeof(foo) which has correct mapping.

foo table has expected data.

foo inherits entityBase which has public virtual prop named Id. simple _session.Get(ids[0]) works.

Stack trace:

[NullReferenceException: Object reference not set to an instance of an object.]
NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetEntityName(ICriteria 
subcriteria, String propertyName) +13
NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetType(ICriteria 
subcriteria, String propertyName) +19
NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetTypeUsingProjection
(ICriteria subcriteria, String
propertyName) +94
NHibernate.Criterion.InExpression.AssertPropertyIsNotCollection(ICriteriaQuery 
criteriaQuery, ICriteria
criteria) +19
NHibernate.Criterion.InExpression.ToSqlString(ICriteria criteria, ICriteriaQuery 
criteriaQuery, IDictionary`2 enabledFilters) +38
NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetWhereCondition
(IDictionary`2 enabledFilters) +223
NHibernate.Loader.Criteria.CriteriaJoinWalker..ctor(IOuterJoinLoadable 
persister, CriteriaQueryTranslator
translator, ISessionFactoryImplementor factory, CriteriaImpl criteria, String 
rootEntityName, IDictionary`2 enabledFilters) +296
NHibernate.Loader.Criteria.CriteriaLoader..ctor(IOuterJoinLoadable persister, 
ISessionFactoryImplementor
factory, CriteriaImpl rootCriteria, String rootEntityName, IDictionary`2 
enabledFilters) +131
NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) +173
NHibernate.Impl.CriteriaImpl.List(IList results) +41
NHibernate.Impl.CriteriaImpl.List() +35

This one does not work either:

IList<T> result =  
  (_session.Linq<T>().Where(a => new[] {1}.Contains(a.Id))).ToList();

Strange, but this works:

IList<foo> result =  
  (_session.Linq<foo>().Where(a => new[] {1}.Contains(a.Id))).ToList();

This one works too:

IList<T> result =_session.Linq<T>()
  .Where(x => 1==1).ToList();

But i need it to be generic.

Any ideas what might be wrong?

Maybe switching to nhibernate 2.1 beta would help?

At the moment it's like this:

public IList<TEntity> GetByMultipleIds(int[] ids)
    {
        //TODO: somehow query whole list at once
        List<TEntity> result = new List<TEntity>();

        foreach (var id in ids) {
            int tempId = id;
            result.Add(_session.Get<TEntity>(tempId));
        }

        return result;
    }

But that's just a lame patch. :/


Actually - my co-worker found a workaround using ICriteria (i'll add code later).
And this allows to sort entities by id array elegantly.

like image 251
Arnis Lapsa Avatar asked Jun 12 '09 13:06

Arnis Lapsa


1 Answers

Damn. I've forgot to add solution that works:

public virtual IList<TEntity> GetByMultipleIds(int[] ids)
{
    var result = Session
      .CreateCriteria(typeof (TEntity))
      .Add(Restrictions.In("Id", ids))
      .List<TEntity>();

    result = ids.Join //to order list by passed ids
      (result, id => id, r => r.Id, (i, r) => r).ToList();

    return result;
}
like image 136
Arnis Lapsa Avatar answered Oct 09 '22 14:10

Arnis Lapsa