【问题标题】:LINQ to NHibernate, "get by array of ids" queryLINQ to NHibernate,“通过 id 数组获取”查询
【发布时间】:2009-06-12 13:16:01
【问题描述】:

代码:

 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 的解决方法(我稍后会添加代码)。
this 允许优雅地按 id 数组对实体进行排序。

【问题讨论】:

    标签: .net linq nhibernate


    【解决方案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;
    }
    

    【讨论】:

      【解决方案2】:

      请记住,NHibernate 继承了您的类,并且不会根据 IList 的实现直接使用它们。可能不是您想听到的,但是由于您的类被代理了,并且当前的 Linq 实现根本无法正确处理它,这就是问题所在。

      在 Linq 的标准中使用代理类的泛型方法的组合在当前实现中出现了很多方面的问题。就像 ShaneC 在他的 cmets 中所说的那样,他们有充分的理由回去并从头开始重新编写它。

      我知道你在修复后,但遗憾的是,在这种情况下,答案是等待 NHibernate 2.1 完成或使用你现在正在做的解决方法。

      【讨论】:

      【解决方案3】:

      我的理解是当前的 Linq to NHibernate 实现相当有限。
      目前正在努力使用此处提供的最新更新对其进行重写:

      Linq To NHibernate Update

      【讨论】:

      • 我不认为我要求太多。 ://
      • 基于他们在新的 Linq to NHibernate 实现上必须做出的改变(有人重写/移植?整个 HQL 解析器)我怀疑旧方法存在一些相当大的限制.
      • 从个人经验来看,我不会相信 Ayende 的宠物项目用于生产代码。更新是零星的,很少以发布的形式出现
      • 我相信NHibernate迟早会支持LINQ。不管谁来帮忙。
      • 目前正在实施 LINQ to NHibernate 的工作。在接下来的几个月里看到一些东西我不会感到惊讶。
      【解决方案4】:

      这个问题的最新答案是它现在可以工作了(NHib 3.3 并且可能 > 3.0)

       var entities = from m in Session.Query<MyEntity>()
                      where ids.Contains(m.ID)
                      select m;
      
       return entities.ToList()
      

      运行正确的查询,例如

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-15
        • 1970-01-01
        • 2020-01-04
        • 1970-01-01
        • 1970-01-01
        • 2013-11-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多