2013-09-04 7 views
6

Es gibt eine Möglichkeit, diese SQL-Anweisung in einen NHibernate-Kriterien zu konvertieren?SQL Union nach NHibernate Kriterien

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

Ich habe festgestellt, dass NHibernate Unions nicht unterstützt.

+1

Sie die answear hier sehen können: http://stackoverflow.com/questions/8591200/union-with-nhibernate-and-criteria – Cesar

Antwort

3

Also habe ich zwei Lösungen gefunden. Ich führe jede Abfrage getrennt durch, als ich die Ergebnisse beschreibe. Es ist wie eine Union, wird aber nicht in der DB ausgeführt, sondern im Gedächtnis.

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

ODER

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

Sie die Objekte sind geladen in Erinnerung, dann Vereinigung. Können Sie die Verbindung vor dem Laden der Objekte im Speicher herstellen? In diesem Fall kann die SQL-Abfrage alle Duplikate entfernen oder weitere Fetches anwenden, die gut funktionieren könnten. –

+0

Union wird zum Zeitpunkt des Verfassens dieses Schreibens immer noch nicht von NHibernate linq unterstützt. Wenn die Ergebnismenge klein genug ist, sollte es in Ordnung sein, sie im Speicher zu vereinen, sonst würde ich lieber eine benannte Abfrage verwenden. –

2

Verwenden Sie eine Ansicht. Es kann direkt in NHibernate abgebildet werden und ist nicht auf eine bestimmte Datenbankimplementierung angewiesen. Sie sollten die Where-Klauseln entfernen und dann können Sie Ihre NHibernate-Kriterien für "Name" und "FullName" erstellen.

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