NHibernate QueryOver-无路径连接(或使用“反向”路径连接)

NHibernate QueryOver-无路径连接(或使用“反向”路径连接),nhibernate,queryover,nhibernate-criteria,Nhibernate,Queryover,Nhibernate Criteria,我试图在没有单个根实体的情况下获取多个实体(实体关系的有向图只是一个弱连通图,而不是强连通图),我不知道如何在Nhibernates QueryOver api(或Linq)中实现这一点,但这似乎更弱) 以下是我的关系: ClientTaxEntity参考文献1Client和NManufacturers 说明书模板参考1客户和1制造商 我希望获得所有可能的客户机-制造商对的结果(可能=它们在一个ClientTaxEntity中在一起),如果存在模板,则向它们获取模板(否则为null) 这就是我迄

我试图在没有单个根实体的情况下获取多个实体(实体关系的有向图只是一个弱连通图,而不是强连通图),我不知道如何在Nhibernates QueryOver api(或Linq)中实现这一点,但这似乎更弱)

以下是我的关系:

ClientTaxEntity
参考文献1
Client
和N
Manufacturers

说明书模板
参考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());