Dot-Net

LINQ to NHibernate,“通過 id 數組獲取”查詢

  • March 29, 2016

程式碼:

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;
}

引用自:https://stackoverflow.com/questions/986582