nhibernate transform linq-to-nhibernate criteria-api nhibernate-queryover

nhibernate - Cómo escribir esta consulta linq con Criteria o la API QueryOver



transform linq-to-nhibernate (1)

¿Es posible convertir este código a continuación, escrito utilizando la aplicación Query (linq) a Criteria o la API QueryOver en NHibernate? Estoy usando esto para formatear datos en DTO, también funciona con solo un viaje de ida y vuelta a db.

Nota: Intenté transformers.aliastobean, pero solo puedo usar un transformador a la vez. ¿Es posible usar transformadores múltiples en una consulta?

from entityType in Provider.GetSession().Query<crmEntityType>() .Fetch(x => x.Association) .Fetch(x => x.Fields) .AsEnumerable() where instanceIDs.Contains(entityType.Instance.instanceID) select new EntityTypeDTO() { ID = entityType.ID, Title = entityType.Title, Association = entityType.Association.Distinct().Select(asc => asc.ID).ToArray<int>(), Fields = entityType.Fields.Distinct().Select(fi => new CustomFieldDTO { ID = fi.ID, Name = fi.Name, Value = fi.Value, EntityType = fi.EntityType.ID, Type = fi.Type }).ToList() }).ToList();


Comencemos con la sintaxis de QueryOver :

// external filter data instanceIDs = new int[] { 1, 2, 3 }; // aliasing EntityTypeDTO entityDTO = null; CustomFieldDTO fieldDTO = null; Field field = null; IQueryOver<EntityType, Field> query = Session.QueryOver<EntityType>() // filter Entity by ID''s list .Where(Restrictions.On<EntityType>(c => c.ID).IsIn(instanceIDs)) // Join Fields .JoinQueryOver<Field>(c => c.Fields, () => field) .SelectList(list => list // entity .Select(c => c.ID) .Select(c => c.Title) // ... more Entity properties // field collection .Select(() => field.ID) .Select(() => field.Name) // ... more Field properties ) .TransformUsing(new MyTransformer()); // see below var dtos = query.List<EntityTypeDTO>();

Este QueryOver generará la declaración SQL que contendrá todos los EntityTypes con sus campos. Ahora tenemos que extraer las instancias exclusivas de EntityType y llenar sus listas de Campos

Hay una descripción general de las clases de DTO (además de QueryOver anterior, estas contienen solo algunas propiedades como ejemplo):

public class EntityTypeDTO { public virtual int ID { get; set; } public virtual string Title { get; set; } public virtual IList<CustomFieldDTO> Fields { get; set; } ... } public class CustomFieldDTO { public virtual int ID { get; set; } public virtual string Name { get; set; } ... }

Y finalmente, el truco de MyTransformer () :

public class MyTransformer : IResultTransformer { // rows iterator public object TransformTuple(object[] tuple, string[] aliases) { var entity = new EntityTypeDTO { ID = (int)tuple[0], // aliases should be used Title = tuple[1] as string // first two are belong to Entity }; var field = new CustomFieldDTO { ID = (int)tuple[2], // last 2 columns are for a Field Name = tuple[3] as string // see SelectList in QueryOver }; entity.Fields = new List<CustomFieldDTO> { field }; return entity; } // convert to DISTINCT list with populated Fields public System.Collections.IList TransformList(System.Collections.IList collection) { var results = new List<EntityTypeDTO>(); foreach(var item in collection) { var entity = item as EntityTypeDTO; // was already the same ID appended var existing = results.SingleOrDefault(c => c.ID.Equals(entity.ID)); if(existing != null) { // extend fields existing.Fields.Add(entity.Fields.First()); continue; } // new ID found results.Add(entity); } // DISTINCT list of Entities, with populated FIELDS return results; } ...

MyTransformer es ad hoc, solo para este propósito ... pero este enfoque podría extenderse