Pregunta

Mi proyecto actual está utilizando NHibernate 3.0b1 y la API NHibernate.Linq.Query<T>(). Estoy bastante fluidez en LINQ, pero no tengo absolutamente ninguna experiencia con HQL o la API ICriteria. Una de mis preguntas no es apoyada por la API IQueryable, así que supongo que necesito utilizar una de las API anteriores - pero no tengo ni idea de por dónde empezar

.

He intentado buscar en la web para un buen "inicio" guía a ICriteria, pero los únicos ejemplos que he encontrado son o bien demasiado simplista para aplicar aquí o demasiado avanzado para mí entender. Si alguien tiene materiales para pasar a lo largo aprendizaje de algún bien, sería muy apreciado.

En cualquier caso, el modelo de objetos de consulta que estoy en contra es similar al siguiente (en gran medida simplificados, propiedades no relevantes omite):

class Ticket {
    IEnumerable<TicketAction> Actions { get; set; }
}
abstract class TicketAction {
    Person TakenBy { get; set; }
    DateTime Timestamp { get; set; }
}
class CreateAction : TicketAction {}
class Person {
    string Name { get; set; }
}

A Ticket tiene una colección de TicketAction que describe su historia. subtipos incluyen TicketAction CreateAction, ReassignAction, CloseAction, etc. Todos los boletos tienen un CreateAction añadido a esta colección cuando se creó.

Esta consulta LINQ es la búsqueda de entradas creadas por alguien con el nombre dado.

var createdByName = "john".ToUpper();
var tickets = _session.Query<Ticket>()
    .Where(t => t.Actions
        .OfType<CreateAction>()
        .Any(a => a.TakenBy.Name.ToUpper().Contains(createdByName));

El método OfType<T>() causa una NotSupportedException a ser lanzado. ¿Puedo hacer esto utilizando ICriteria lugar?

¿Fue útil?

Solución

intentar algo como esto. Es sin compilar, pero debería funcionar siempre y cuando IEnumerable<TicketAction> Actions y Person TakenBy no es nulo. Si lo establece en una lista vacía en el constructor de entradas, que va a resolver un problema con nulos.

Si se agrega una referencia al objeto de entradas en el TicketAction, se podría hacer algo como esto:

ICriteria criteria = _session.CreateCriteria(typeof(CreateAction))
   .Add(Expression.Eq("TakenBy.Name", createdByName));

var actions = criteria.List<CreateAction>();

var results = from a in criteria.List<>()
   select a.Ticket;

En mi experiencia, nhibernate tiene problemas con criterios cuando se trata de listas cuando la lista está en el lado del objeto - como es su caso. Cuando se trata de una lista de valores en el lado de entrada, puede utilizar Expression.Eq. Siempre he tenido que encontrar maneras de evitar esta limitación a través de LINQ, donde consigo un conjunto de resultados inicial se filtraba lo mejor que puedo, después se filtra de nuevo con LINQ para conseguir lo que necesito.

Otros consejos

OfType es compatible. No estoy seguro de ToUpper es, sin embargo, sino como SQL ignora caso no importa (siempre que no se esté ejecutando también la consulta en la memoria ...). Aquí está una prueba de unidad de trabajo del proyecto nHibernate.LINQ:

var animals = (from animal in session.Linq<Animal>()
               where animal.Children.OfType<Mammal>().Any(m => m.Pregnant)
               select animal).ToArray();
Assert.AreEqual("789", animals.Single().SerialNumber);

Tal vez su consulta debe parecerse más a lo siguiente:

var animals = (from ticket in session.Linq<Ticket>()
               where ticket.Actions.OfType<CreateAction>().Any(m => m.TakenBy.Name.Contains("john"))
               select ticket).ToArray();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top