Ibernazione:Clausola CreateCriteria ed Exists
-
20-09-2019 - |
Domanda
Come posso scrivere il seguente SQL utilizzando CreateCriteria:
SELECT * FROM FooBar fb
WHERE EXISTS (SELECT FooBarId FROM Baz b WHERE b.FooBarId = fb.Id)
Soluzione 3
Ho lavorato come fare ciò utilizzando l'espressione IsNotEmpty. Qui si sta usando estensioni NHibernate Lambda:
Session.CreateCriteria<FooBar>()
.Add(SqlExpression.IsNotEmpty<FooBar>(x => x.Bazes))
.List<FooBar>();
Altri suggerimenti
Ecco come si può fare:
var fooBars = Session.CreateCriteria<FooBar>()
.Add(Restrictions.IsNotEmpty("Bazs")).List<FooBar>();
... c'è assumendo è una proprietà della raccolta (uno-a-molti) "Bazs" nell'oggetto FooBar.
In alternativa è possibile utilizzare criteri staccati così:
DetachedCriteria dCriteria = DetachedCriteria.For<Baz>("baz")
.SetProjection(Projections.Property("baz.FooBarId"))
.Add(Restrictions.EqProperty("baz.FooBarId", "fooBar.Id"));
var fooBars = Session.CreateCriteria<FooBar>("fooBar")
.Add(Subqueries.Exists(dCriteria)).List<FooBar>();
Avendo appena risolto un problema correlato e alla fine arrivato a una soluzione, ho pensato di condividere la risposta qui:
Supponendo che tu voglia la query delle domande originali, con una condizione aggiuntiva nella sottoquery:
SELECT * FROM FooBar fb
WHERE EXISTS (SELECT FooBarId FROM Baz b WHERE b.FooBarId = fb.Id
AND Quantity = 5)
Supponendo che tu abbia un riferimento sulla classe Baz al genitore, chiamato, diciamo FooBarRef [nella classe Fluent Map utilizzeresti il metodo References() ], creerai la query come segue:
DetachedCriteria dCriteria = DetachedCriteria.For<Baz>("baz")
.SetProjection(Projections.Property("baz.FooBarId"))
.Add(Expression.EqProperty("this.FooBarId", "FooBarRef.Id"))
.Add(Expression.Eq("baz.Quantity", 5));
var fooBars = Session.CreateCriteria<FooBar>("fooBar")
.Add(Subqueries.Exists(dCriteria)).List<FooBar>();
Non sono convinto al 100% dell'hard coding dell'alias "this", che è l'alias che NHibernate assegna automaticamente all'entità root (tabella) nella query, ma è l'unico modo che ho trovato per fare riferimento alla chiave del tabella della query principale dall'interno della sottoquery.