nhibernate - 如何使用 Criteria 或 QueryOver API 编写此 linq 查询

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

是否可以将下面使用 Query(linq) api 编写的代码转换为 NHibernate 中的 Criteria 或 QueryOver API?我使用它来将数据格式化为 DTO,而且它只需与数据库进行一次往返即可工作。

注意:我尝试了transformers.aliastobean,但一次只能使用一个变压器。是否可以在一个查询中使用多个转换器?

     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();

最佳答案

让我们从 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>();

此 QueryOver 将生成 SQL 语句,其中包含所有 EntityType 及其字段。现在我们必须提取唯一的 EntityType 实例并填充它们的字段列表

这里有 DTO 类的概述(以及上面的 QueryOver,这些仅包含很少的属性作为示例):

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

最后是技巧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 是临时的,仅用于此目的......但这种方法可以扩展

关于nhibernate - 如何使用 Criteria 或 QueryOver API 编写此 linq 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13803398/

相关文章:

linq - 如何在 linq to NHibernate 中使用 if 条件为可空 bool 值

linq - NHibernate.Linq赞

c# - 如何通过 NHibernate 从表中获取数据?

CSS 转换属性 - 在 IE9 和 IE10 上的结果不一致

python - 有没有办法在 Python 的 Matplotlib 中以点坐标绘制 Line2D?

c#-4.0 - NHIBERNATE WHERE 和 IQUERYOVER 的多个 OR 子句

c# - Dispose() 如何知道它是因为异常而被调用的?

.net - 为 POINT postgresql 数据类型(或非原始类似 nhibernate 类型的任何 COLUMN)实现新的 NHibernate 类型

mysql - 子查询上的 NHibernate INNER JOIN

html - 使用 transform 时,div 容器仍保持原始图像大小