Соединение SQL с критериями NHibernate

Есть ли способ преобразовать этот оператор SQL в критерии NHibernate?

(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 не поддерживает союзы.


person Alexandre Vicenzi    schedule 04.09.2013    source источник
comment
Вы можете увидеть ответ здесь: stackoverflow.com/questions/ 8591200 /   -  person Cesar    schedule 05.09.2013


Ответы (2)


Попробуйте использовать представление. Он может быть отображен непосредственно в NHibernate и не зависит от конкретной реализации базы данных. Вам следует удалить предложения where, а затем вы можете построить свои критерии NHibernate на основе «Name» и «FullName».

  (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)
person Thierry    schedule 04.09.2013

Итак, я нашел два решения. Я выполняю каждый запрос отдельно, чем объединяю результаты. Это похоже на Union, но выполняется не в БД, а в памяти.

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

OR

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);
person Alexandre Vicenzi    schedule 05.09.2013
comment
вы загружаете объекты в память, а затем объединяете. Можете ли вы объединить перед загрузкой объектов в память? в этом случае SQL-запрос может удалить любые дублирования или, если вам нужно будет применить дополнительные выборки, которые могут работать нормально. - person The Light; 09.01.2014
comment
На момент написания этой статьи Union все еще не поддерживается NHibernate linq. Полученный набор результатов достаточно мал, и его должно быть хорошо объединить в памяти, в противном случае я бы предпочел использовать именованный запрос. - person Alex M; 18.11.2015