Or Constraint for QueryOver - nhibernate

I want to get all PartitionStates by name where it exactly meets the partitionName or starts with it when containing a ..
This is the query I have
return session.QueryOver<PartitionState>()
.Where(p => p.Name == partitionName)
.WhereRestrictionOn(p => p.Name).IsLike(partitionName + ".", MatchMode.Start)
.OrderBy(p => p.StartDate).Desc
.Take(1)
.SingleOrDefault<PartitionState>();
The above query produces an AND expression, but i want it to be an OR.
In SQL it should look like this:
SELECT TOP 1 *
FROM PartitionState
WHERE (Name = #partitionName OR Name like #partitionName+'.%')
ORDER BY StartDate DESC

It seems there is no built in method, but it is possible to pass a restriction into where method.
return session.QueryOver<PartitionState>()
.Where(Restrictions.Or(
Restrictions.Where<PartitionState>(p => p.Name == partitionName),
Restrictions.On<PartitionState>(p => p.Name).IsLike(partitionName + ".", MatchMode.Start)))
.OrderBy(p => p.StartDate)
.Desc.Take(1)
.SingleOrDefault<PartitionState>();

Related

NHibernate QueryOver restrict by string length

How do I restrict a query by the length of a string property? eg. something like:
NHSession.QueryOver<Customer>()
.Where(p => p.RegistryCode.Length == 8)
Something like this may do the trick
NHSession.QueryOver<Customer>()
.Where(
Restrictions.Eq(
Projections.SqlFunction("length", NHibernateUtil.String,
Projections.Property<Customer>(x => x.RegistryCode)),
8
)
)
Instead of "NHibernateUtil.String" i should use this "NHibernateUtil.Int16" type, because a 'length' parameter should always be a number and not a String.
Something like this:
NHSession.QueryOver<Customer>()
.Where(
Restrictions.Eq(
Projections.SqlFunction("length", NHibernateUtil.Int16,
Projections.Property<Customer>(x => x.RegistryCode)),
8
)
)

NHibernate QueryOver with JoinQueryOver select all columns

I have some QueryOver with several joins and the result I get is OK in terms of the returned objects. This is the code>
var l = session.QueryOver<Discount>(() => discount)
.JoinQueryOver<ConPrdGrp>(r => r.ConPrdGrps)
.JoinQueryOver<PrdGroupTree>(k => k.PrdGroupTree)
.JoinQueryOver<Product>(g => g.Products)
.Where(p => p.ProductID == Product.ProductID)
.And(() => discount.FomDato <= DateTime.Now && discount.TomDato >= DateTime.Now).List();
But if I look at the SQL statement, I can see that the generated query selects ALL columns from all joined tables although the result only returns a list of Discount objects. I can get some properties of Discount using projections and the query will be much smaller. But how I can instruct NHibernate to get just columns from the Discount table and not from all joined tables?
As far as I know there is NOT a simple way like: .Select(Projections.Properties<Discount>()). Check this a bit outdated question (NHIbernate: Shortcut for projecting all properties?)
What you can do is explicitly name the columns you would like to see:
... // the QueryOver you have
.SelectList (l => l
.Select(() => discount.ID).WithAlias(() => discount.ID)
.Select(() => discount.Code).WithAlias(() => discount.Code)
...
)
.TransformUsing(Transformers.AliasToBean<Discount>())
...
The second approach could be to create the Subquery, and then just QueryOver<Discount>() 16.8. Subqueries
QueryOver<Discount> subQuery =
QueryOver.Of<Discount>(() => innerDiscount)
.JoinQueryOver<ConPrdGrp>(r => r.ConPrdGrps)
.JoinQueryOver<PrdGroupTree>(k => k.PrdGroupTree)
.JoinQueryOver<Product>(g => g.Products)
.Where(p => p.ProductID == Product.ProductID)
.And(() => innerDiscount.FomDato <= DateTime.Now
&& innerDiscount.TomDato >= DateTime.Now).List()
.Select( Projections.Property(() => innerDiscount.ID))
;
var query = session.QueryOver<Discount>(() => discount)
.Where(Subqueries.PropertyIn("ID", subQuery.DetachedCriteria))
;

Rails Arel equivalent of this complex sql query

Here is the original logic
(scrape_datas = ScrapeData.find(
:all, :conditions =>
"artist_status = 'NOT_FOUND'
AND blacklisted = 1
AND extracted = 0
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
I've been able to split up the first part better
scrape_datas = ScrapeData.where(
:artist_status => 'NOT_FOUND',
:blacklisted => 1,
:extracted => 0
)
Although having issues getting the "and not EXISTS" query into the mix
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
Thanks!
Firstly you can extract simple scopes:
scope :not_found, where(:artist_status => 'NOT_FOUND')
scope :blacklisted, where(:blacklisted => 1)
scope :extracted, where(:extracted => 0)
Then add a query method (assume artist_name is a column of scrape_datas):
def self.no_suggestions
scrape_datas = ScrapeData.arel_table
suggestions = ArtistNameSuggestion.arel_table
where(ArtistNameSuggestion.where(
suggestions[:original].eq(scrape_datas[:artist_name])
).exists.not)
end
Now you can do something like this:
ScrapeData.not_found.blacklisted.extracted.no_suggestions

NHibernate QueryOver Restrinctions on a variable

I've a little problem: I would insert a condition into my QueryOver that checks also the variable value. Something like this:
var qOver = QueryOver.Of<MyModel>(() => myMod)
.JoinAlias(() => myMod.SubMod, () => subMod, JoinType.LeftOuterJoin)
.Where(Restrictions.Or(
Restrictions.On(() => myMod.ID).IsIn(MyIDList)
, Restrictions.On(MyIDList == null))
In SQL sintax something like
WHERE #Variable = '' OR MyTable.MyField = #Variable
So, if I my variable is filled I'll filter on my field. If my variable is empty (or null) I'll select every record without filter any content.
How can I reach this result using QueryOver and Restrinctions?
Thank you!
If the variable is null or not set, dont add it to your query.
var qOver = QueryOver.Of<MyModel>(() => myMod)
.JoinAlias(() => myMod.SubMod, () => subMod, JoinType.LeftOuterJoin);
if( MyIDList != null )
qOver = qOver.Where(Restrictions.Or(Restrictions.On(() => myMod.ID).IsIn(MyIDList))

NHibernate Linq where clause: value in collection

I am wondering can I do a where clause that takes in a collection?
List<string> myStrings = new List<strings> {"1", "2"};
session.Query<Table>().Where(x => x.Id == myStrings).ToList();
I basically want to get all rows from my db table that match everything in that query.
session.Query<Table>().Where(x => x.Id == myStrings[0]).ToList();
session.Query<Table>().Where(x => x.Id == myStrings[1]).ToList();
session.Query<Table>().Where(x => x.Id == myStrings[N]).ToList();
So thats what I would have to do right now. I would probably through that in a for loop but that is alot of queryies and I rather just do one query.
Or do I have to use the nhibernate create query syntax
var query = "Select * From Where In (:Id)";
session.CreateQuery(query)SetParameter("Id",myStrings) // not sure if I have to something like .ExecuteUpdate(); but just for select instead
session.Query<Table>().Where(x => myStrings.Contains(s => x.Id));
session.Query<Table>().Where(x => myString.All(s => x.Id == s));
you should use Any or All extension method on your collection