Nhibernate 如何使用条件或QueryOver API编写此linq查询
是否可以将下面的代码转换为NHibernate中使用查询(linq)api编写的Criteria或QueryOver api?我用它来将数据格式化成DTO,而且它只需要一次到db的往返 注意:我尝试了transformers.aliastobean,但一次只能使用一个transformer。是否可以在一个查询中使用多个transformerNhibernate 如何使用条件或QueryOver API编写此linq查询,nhibernate,transform,linq-to-nhibernate,criteria-api,queryover,Nhibernate,Transform,Linq To Nhibernate,Criteria Api,Queryover,是否可以将下面的代码转换为NHibernate中使用查询(linq)api编写的Criteria或QueryOver api?我用它来将数据格式化成DTO,而且它只需要一次到db的往返 注意:我尝试了transformers.aliastobean,但一次只能使用一个transformer。是否可以在一个查询中使用多个transformer from entityType in Provider.GetSession().Query<crmEntityType>()
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();
来自Provider.GetSession().Query()中的entityType
.Fetch(x=>x.Association)
.Fetch(x=>x.Fields)
.可计算的()
其中instanceID.Contains(entityType.Instance.instanceID)
选择新EntityTypeDTO()
{
ID=entityType.ID,
Title=entityType.Title,
Association=entityType.Association.Distinct(),
Fields=entityType.Fields.Distinct().Select(fi=>new CustomFieldDTO{
ID=fi.ID,
Name=fi.Name,
值=fi.值,
EntityType=fi.EntityType.ID,
Type=fi.Type
})托利斯先生()
}).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>();
//外部筛选器数据
instanceId=newint[]{1,2,3};
//混叠
EntityTypeDTO entityDTO=null;
CustomFieldDTO-fieldDTO=null;
字段=空;
IQueryOver query=Session.QueryOver()
//按ID的列表筛选实体
.Where(限制.On(c=>c.ID).IsIn(实例ID))
//连接字段
.JoinQueryOver(c=>c.Fields,()=>field)
.SelectList(list=>list
//实体
.选择(c=>c.ID)
.选择(c=>c.Title)
//…更多实体属性
//野外采集
.选择(()=>field.ID)
.选择(()=>field.Name)
//…更多字段属性
)
.TransformUsing(新的MyTransformer());//见下文
var dtos=query.List();
此查询将生成包含所有EntityTypes及其字段的SQL语句。现在我们必须提取唯一的EntityType实例并填充它们的字段列表
这里概述了DTO类(以及上面的QueryOver,这些类仅包含几个属性作为示例):
公共类EntityTypeDTO
{
公共虚拟整数ID{get;set;}
公共虚拟字符串标题{get;set;}
公共虚拟IList字段{get;set;}
...
}
公共类CustomFieldDTO
{
公共虚拟整数ID{get;set;}
公共虚拟字符串名称{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:IResultTransformer
{
//行迭代器
公共对象转换元组(对象[]元组,字符串[]别名)
{
var实体=新实体类型DTO
{
ID=(int)元组[0],//应使用别名
Title=元组[1]作为字符串//前两个属于实体
};
var字段=新的CustomFieldDTO
{
ID=(int)tuple[2],//最后两列用于字段
Name=元组[3]作为字符串//请参见QueryOver中的SelectList
};
entity.Fields=新列表{field};
返回实体;
}
//转换为具有填充字段的不同列表
public System.Collections.IList转换列表(System.Collections.IList collection)
{
var results=新列表();
foreach(集合中的var项)
{
var entity=作为EntityTypeDTO的项目;
//已经附加了相同的ID
var existing=results.SingleOrDefault(c=>c.ID.Equals(entity.ID));
if(现有!=null)
{
//扩展字段
现有的.Fields.Add(entity.Fields.First());
继续;
}
//找到新ID
结果:增加(实体);
}
//具有填充字段的实体的不同列表
返回结果;
}
...
MyTransformer是一个特别的工具,仅用于此目的……但这种方法可以扩展您认为性能需要这样的实现,还是我用Linq语法编写的第一个查询就足够了?我使用的是Criteria API和QueryOver(没有NHibernate的Linq实现经验)。如果第一个/您的SQL适合您,并且不需要移动到标准…使用它。性能应该相同!生成的两个SQL应该相似。。。
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;
}
...