Dot-Net
LINQ to NHibernate,“通過 id 數組獲取”查詢
程式碼:
public IList<T> GetByMultipleIds(int[] ids) { List<T> result = _session.Linq<T>() .Where(x => ids.Contains(x.Id)).ToList(); return result; }拋出:
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 是具有正確映射的 typeof(foo) 。
foo 表有預期的數據。
foo 繼承了 entityBase,它具有名為 Id 的公共虛擬道具。簡單的 _session.Get(ids
$$ 0 $$) 有效。 堆棧跟踪:
[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這個也不起作用:
IList<T> result = (_session.Linq<T>().Where(a => new[] {1}.Contains(a.Id))).ToList();奇怪,但這有效:
IList<foo> result = (_session.Linq<foo>().Where(a => new[] {1}.Contains(a.Id))).ToList();這個也有效:
IList<T> result =_session.Linq<T>() .Where(x => 1==1).ToList();但我需要它是通用的。
有什麼想法可能是錯的嗎?
也許切換到 nhibernate 2.1 beta 會有所幫助?
目前是這樣的:
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; }但這只是一個蹩腳的更新檔。:/
實際上 - 我的同事找到了使用 ICriteria 的解決方法(我稍後會添加程式碼)。
這允許通過 id 數組優雅地對實體進行排序。
請記住,NHibernate 繼承了您的類,並且不會根據 IList 的實現直接使用它們。可能不是您想听到的,但是由於您的類被代理並且目前的 Linq 實現根本無法正確處理它,這就是問題所在。
在 Linq 的標準中使用代理類的泛型方法的組合在目前實現中以多種方式爆炸。就像 ShaneC 在他的評論中所說的那樣,他們有充分的理由回去並從頭開始重新編寫它。
我知道你在修復後,但遺憾的是,在這種情況下,答案是等待 NHibernate 2.1 完成或使用你現在正在做的變通方法。
該死。我忘了添加有效的解決方案:
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; }