【问题标题】:SQL Union to NHibernate CriteriaSQL 联合到 NHibernate 标准
【发布时间】:2013-09-08 12:14:12
【问题描述】:

有没有办法将此 SQL 语句转换为 NHibernate Criteria?

(select b1.FieldA as Name, b1.FieldA as FullName from Sale b1 where b1.FieldA like '%john%' or b1.FieldA like '%john%' order by b1.Id desc)
union 
(select b2.FieldC as Name, b2.FieldD as FullName from Sale b2 where b2.FieldC like '%john%' or b2.FieldD like '%john%' order by b2.Id desc)
union 
(select c.FieldE as Name, c.FieldF as FullName from Client c where c.FieldE like '%john%' or c.FieldF like '%john%' order by c.Id desc)

我发现 NHibernate 不支持联合。

【问题讨论】:

标签: sql hibernate nhibernate sqlite sybase


【解决方案1】:

尝试使用视图。它可以直接在 NHibernate 中映射,不依赖于特定的数据库实现。您应该删除 where 子句,然后您可以针对“Name”和“FullName”构建您的 NHibernate 标准。

  (select b1.FieldA as Name, b1.FieldA as FullName from Sale b1 order by b1.Id desc)
  union 
  (select b2.FieldC as Name, b2.FieldD as FullName from Sale b2 order by b2.Id desc)
  union 
  (select c.FieldE as Name, c.FieldF as FullName from Client c order by c.Id desc)

【讨论】:

    【解决方案2】:

    所以,我找到了两种解决方案。我分别执行每个查询而不是连接结果。它就像一个联合,但不是在数据库中执行,而是在内存中执行。

    var b1 = Session.Query<Sale>()
                .Where(x => x.FiledA.Contains(filter) || x.FiledB.Contains(filter))
                .OrderBy(x => x.Id)
                .GroupBy(x => new { x.FiledA, x.FiledB })
                .Select(x => new Foo { FullName = x.Key.FiledA, Name = x.Key.FiledB })
                .Take(30)
                .ToList();
    
    var b2 = Session.Query<Sale>()
                .Where(x => x.FiledC.Contains(filter) || x.FiledD.Contains(filter))
                .OrderBy(x => x.Id)
                .GroupBy(x => new {x.FiledC, x.FiledD})
                .Select(x => new Foo {FullName = x.Key.FiledC, Name = x.Key.FiledD})
                .Take(30)
                .ToList();
    
    
    var c = Session.Query<Client>()
                .Where(x => x.FiledE.Contains(filter) || x.FiledF.Contains(filter))
                .OrderBy(x => x.Id)
                .GroupBy(x => new { x.FiledE, x.FiledF })
                .Select(x => new Foo { FullName = x.Key.FiledE, Name = x.Key.FiledF })
                .Take(30)
                .ToList();
    
    return b1.Concat(b2)
             .Concat(c)
             .ToList()
             .GroupBy(x => new { x.Name, x.FullName })
             .Select(x => x.First())
             .Take(30);
    

    var b1 = Session.CreateCriteria<Sale>()
        .SetProjection(Projections.ProjectionList()
            .Add(Projections.Distinct(Projections.Property("FiledA")), "Name")
            .Add(Projections.Property("FiledB"), "FullName"))
        .Add(Restrictions.Or(Restrictions.InsensitiveLike("FiledA", filter),
            Restrictions.InsensitiveLike("FiledB", filter)))
        .AddOrder(Order.Desc("Id"))
        .SetMaxResults(30)
        .SetResultTransformer(Transformers.AliasToBean<Foo>())
        .List<Foo>();
    
    var b2 = Session.CreateCriteria<Sale>()
        .SetProjection(Projections.ProjectionList()
            .Add(Projections.Distinct(Projections.Property("FiledC")), "Name")
            .Add(Projections.Property("FiledD"), "FullName"))
        .Add(Restrictions.Or(Restrictions.InsensitiveLike("FiledC", filter),
            Restrictions.InsensitiveLike("FiledD", filter)))
        .AddOrder(Order.Desc("Id"))
        .SetMaxResults(30)
        .SetResultTransformer(Transformers.AliasToBean<Foo>())
        .List<Foo>();
    
    var c = Session.CreateCriteria<Client>()
        .SetProjection(Projections.ProjectionList()
            .Add(Projections.Distinct(Projections.Property("FiledE")), "Name")
            .Add(Projections.Property("FieldF"), "FullName"))
        .Add(Restrictions.Or(Restrictions.InsensitiveLike("FiledE", filter),
            Restrictions.InsensitiveLike("FieldF", filter)))
        .AddOrder(Order.Desc("Id"))
        .SetMaxResults(30)
        .SetResultTransformer(Transformers.AliasToBean<Foo>())
        .List<Foo>();
    
    return b1.Concat(b2)
             .Concat(c)
             .ToList()
             .GroupBy(x => new {x.FullName, x.Name})
             .Select(x => x.First())
             .Take(30);
    

    【讨论】:

    • 您将对象加载到内存中,然后合并。您可以在将对象加载到内存之前合并吗?在这种情况下,SQL 查询可以删除任何重复,或者如果您需要应用可以很好地工作的进一步 Fetch。
    • 在撰写本文时,NHibernate linq 仍然不支持联合。取得的结果集足够小,应该可以在内存中合并,否则我宁愿使用命名查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多