Reputation: 47597
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.
Upvotes: 13
Views: 7641
Reputation: 8343
The latest answer to this question is that it now works (NHib 3.3 and probably > 3.0)
var entities = from m in Session.Query<MyEntity>()
where ids.Contains(m.ID)
select m;
return entities.ToList()
Runs the right query, something like
exec sp_executesql N'select MyEntity0_.ID as ID47_, MyEntity0_.Name as Name47_ from Groups MyEntity0_ where MyEntity0_.ID in (@p0 , @p1)',N'@p0 int,@p1 int',@p0=175,@p1=176
Upvotes: 1
Reputation: 47597
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;
}
Upvotes: 8
Reputation: 630409
Remember that NHibernate inherits your classes and doesn't use them directly per it's implementation of IList. Probably not what you want to hear but since your classes are proxied and the current Linq implementation doesn't handle it correctly at all, that's where the problem comes in.
The combination of a generic method using a proxied class in criteria for Linq just blows up in so many ways with the current implementation. Like ShaneC said in his comments, there's good reason they went back and started re-writing it from scratch.
I know your after a fix, but sadly the answer in this case is wait for NHibernate 2.1 to be complete or use a work-around like you are doing for now.
Upvotes: 6
Reputation: 14097
My understanding is that the current Linq to NHibernate implementation is fairly limited.
There is currently an effort to rewrite it with the latest updating being available here:
Upvotes: 1