NHibernate QueryOver-无路径连接(或使用“反向”路径连接)
我试图在没有单个根实体的情况下获取多个实体(实体关系的有向图只是一个弱连通图,而不是强连通图),我不知道如何在Nhibernates QueryOver api(或Linq)中实现这一点,但这似乎更弱) 以下是我的关系:NHibernate QueryOver-无路径连接(或使用“反向”路径连接),nhibernate,queryover,nhibernate-criteria,Nhibernate,Queryover,Nhibernate Criteria,我试图在没有单个根实体的情况下获取多个实体(实体关系的有向图只是一个弱连通图,而不是强连通图),我不知道如何在Nhibernates QueryOver api(或Linq)中实现这一点,但这似乎更弱) 以下是我的关系: ClientTaxEntity参考文献1Client和NManufacturers 说明书模板参考1客户和1制造商 我希望获得所有可能的客户机-制造商对的结果(可能=它们在一个ClientTaxEntity中在一起),如果存在模板,则向它们获取模板(否则为null) 这就是我迄
ClientTaxEntity
参考文献1Client
和NManufacturers
说明书模板
参考1客户
和1制造商
我希望获得所有可能的客户机-制造商对的结果(可能=它们在一个ClientTaxEntity中在一起),如果存在模板,则向它们获取模板(否则为null)
这就是我迄今为止所尝试的:
Client client = null;
Manufacturer manufacturer = null;
InstructionTemplate template = null;
ClientTaxEntity taxEntity = null;
InstructionTemplateInfo info = null;
var query =Session.QueryOver<ClientTaxEntity>(() => taxEntity)
.JoinAlias(x => x.Client, () => client)
.JoinAlias(x => x.Manufacturers, () => manufacturer)
.Left
.JoinQueryOver(() => template, () => template,() => template.Client == client && template.Manufacturer == manufacturer);
var result = query
.SelectList(builder => builder
.Select(() => client.Name).WithAlias(() => info.ClientName)
.Select(() => client.Id).WithAlias(() => info.ClientId)
.Select(() => manufacturer.Name).WithAlias(() => info.ManufacturerName)
.Select(() => manufacturer.Id).WithAlias(() => info.ManufacturerId)
.Select(() => template.Id).WithAlias(() => info.TemplateId)
.Select(() => template.Type).WithAlias(() => info.Type)
)
.TransformUsing(Transformers.DistinctRootEntity)
.TransformUsing(Transformers.AliasToBean<InstructionTemplateInfo>())
.List<InstructionTemplateInfo>();
Client=null;
制造商=空;
InstructionTemplate模板=null;
ClientTaxEntity taxEntity=null;
InstructionTemplateInfo=null;
var query=Session.QueryOver(()=>taxEntity)
.JoinAlias(x=>x.Client,()=>Client)
.JoinAlias(x=>x.Manufacturers,()=>manufacturer)
左边
.JoinQueryOver(()=>template,()=>template,()=>template.Client==Client&&template.Manufacturer==Manufacturer);
var结果=查询
.SelectList(生成器=>builder
。选择(()=>client.Name)。使用别名(()=>info.ClientName)
。选择(()=>client.Id)。使用别名(()=>info.ClientId)
。选择(()=>manufacturer.Name)。使用别名(()=>info.ManufacturerName)
。选择(()=>manufacturer.Id)。使用别名(()=>info.ManufacturerId)
。选择(()=>template.Id)。使用别名(()=>info.TemplateId)
。选择(()=>template.Type)。使用别名(()=>info.Type)
)
.变压器使用(变压器.距离)
.TransformUsing(Transformers.AliasToBean())
.List();
信息对象是我想要的结果
但是,语法
.JoinQueryOver(()=>template
似乎对路径参数无效(例外情况是:无法解析属性:template of:ClientTaxEntity
要在SQL中编写查询时获得所需的结果,必须编写以下内容:
SELECT Client_Id, Client_Name, Manufacturer_Id, Manufacturer_Name
FROM
(
SELECT Client.Id as Client_Id, Client.Name as Client_Name,
Manufacturer.Id as Manufacturer_Id, Manufacturer.Name as Manufacturer_Name
FROM ClientTax
INNER JOIN Client on Client.Id = ClientTax.Client_Id
INNER JOIN Manufacturer on Manufacturer.Id = Manufacturer.Manufacturer_id
UNION
SELECT Client.Id, Client.Name, Manufacturer.Id, Manufacturer.Name
FROM InstructionTemplate
INNER JOIN Client on Client.Id = InstructionTemplate.Client_Id
INNER JOIN Manufacturer on Manufacturer.Id = InstructionTemplate.Manufacturer_id
) a
GROUP BY Client_Id, Client_Name, Manufacturer_Id, Manufacturer_Name;
不幸的是,将这样的查询转换为NHibernate的查询API之一是不可能的,因为NHibernate不支持UNION语句*。请参阅NHibernate的bug tracker中的这一点和功能请求
*使用联合子类时除外。有关详细信息,请参阅
我能看到的唯一选择是
执行SQL查询并将其映射到DTO
public class InstructionTemplateInfo
{
public int Client_Id { get; set; }
public string Client_Name { get; set; }
public int Manufacturer_Id { get; set; }
public string Manufacturer_Name { get; set; }
}
然后
这种方法的优点是DBMS只会被命中一次。
有关此功能的更多详细信息,请参阅
我知道我可以在两个查询中完成,因为我有两个根实体,但我正在寻找一个DB查询解决方案。ClientTaxEntity
和InstructionTemplate
之间是否存在关系?不,没有。我还尝试用subselect替换连接,但如果subselect的结果产生的值超过1 va,则失败lueI采用了未来的方法,这正是我所需要的。谢谢。很遗憾,NHibernate不支持工会,但它看起来需要很多改变才能发挥作用。幸运的是,NHibernate非常灵活,解决问题的方法几乎总是不止一种。
var result = session
.CreateSQLQuery(theSQLQueryString)
.SetResultTransformer(Transformers.AliasToBean<InstructionTemplateInfo>())
.List<InstructionTemplateInfo>();
var resultSet1 = Session.QueryOver<ClientTaxEntity>(() => taxEntity)
.JoinAlias(x => x.Client, () => client)
.JoinAlias(x => x.Manufacturers, () => manufacturer)
.SelectList(builder => builder
.SelectGroup((() => client.Name).WithAlias(() => info.ClientName)
.SelectGroup((() => client.Id).WithAlias(() => info.ClientId)
.SelectGroup((() => manufacturer.Name).WithAlias(() => info.ManufacturerName)
.SelectGroup((() => manufacturer.Id).WithAlias(() => info.ManufacturerId)
.TransformUsing(Transformers.AliasToBean<InstructionTemplateInfo>())
.Future<InstructionTemplateInfo>;
var resultSet2 = Session.QueryOver<InstructionTemplate>(() => taxEntity)
.JoinAlias(x => x.Client, () => client)
.JoinAlias(x => x.Manufacturers, () => manufacturer)
.SelectList(builder => builder
.SelectGroup((() => client.Name).WithAlias(() => info.ClientName)
.SelectGroup((() => client.Id).WithAlias(() => info.ClientId)
.SelectGroup((() => manufacturer.Name).WithAlias(() => info.ManufacturerName)
.SelectGroup((() => manufacturer.Id).WithAlias(() => info.ManufacturerId)
.TransformUsing(Transformers.AliasToBean<InstructionTemplateInfo>())
.Future<InstructionTemplateInfo>;
var result = resultSet1.Concat(resultSet2 )
.GroupBy(x=>x.ClientId+"|"+x.ManufacturerId)
.Select(x=>x.First());