sqlquery query .net linq nhibernate

.net - sqlquery - nhibernate sql query string



LINQ to NHibernate, consulta "obtener por matriz de ids" (4)

Código:

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

Lanza:

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 es typeof (foo) que tiene un mapeo correcto.

la tabla foo tiene datos esperados.

foo hereda entityBase que tiene un elemento virtual público llamado Id. simple _session.Get (ids [0]) funciona.

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

Este tampoco funciona:

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

Extraño, pero esto funciona :

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

Este también funciona :

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

Pero necesito que sea genérico.

¿Alguna idea de lo que podría estar mal?

Tal vez cambiar a nhibernate 2.1 beta ayudaría?

Por el momento es así:

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

Pero eso es solo un parche cojo. : /

En realidad, mi compañero de trabajo encontró una solución con ICriteria (agregaré el código más adelante).
Y esto permite ordenar entidades por matriz de id con elegancia.


La última respuesta a esta pregunta es que ahora funciona (NHib 3.3 y probablemente> 3.0)

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

Ejecuta la consulta correcta, algo así como

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


Maldita sea. Olvidé agregar una solución que funciona:

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


Recuerda que NHibernate hereda tus clases y no las usa directamente por su implementación de IList. Probablemente no sea lo que quiere escuchar, pero dado que sus clases están procesadas y la implementación actual de Linq no lo maneja correctamente, ahí es donde entra el problema.

La combinación de un método genérico que utiliza una clase proxy en los criterios para Linq simplemente explota de muchas maneras con la implementación actual. Al igual que ShaneC dijo en sus comentarios, hay buenas razones por las que regresaron y comenzaron a reescribirlo desde cero.

Lo sé después de una solución, pero lamentablemente la respuesta en este caso es esperar a que NHibernate 2.1 esté completo o usar una solución temporal como lo está haciendo por ahora.


Tengo entendido que la implementación actual de Linq a NHibernate es bastante limitada.
Actualmente hay un esfuerzo para reescribirlo con la última actualización disponible aquí:

Actualización de Linq a NHibernate