NHibernate: DetachedCriteria nesting more than once - nhibernate

I can't get DetachedCriteria to work properly after nesting more than once, the reason being that the DetatchedCriteria can only access aliased entities one layer higher.
The following doesn't work, for example:
var secondNestedCriteria = DetachedCriteria.For<Baz>("baz")
.SetProjection(Projections.Id())
.Add(Restrictions.EqProperty("baz.FooName", "foo.Name") // Doesn't work
.Add(Restrictions.EqProperty("baz.BarName", "bar.Name");
var firstNestedCriteria = DetachedCriteria.For<Bar>("bar")
.SetProjection(Projections.Id())
.Add(Restrictions.EqProperty("bar.FooName", "foo.Name")
.Add(Subqueries.Exists(secondNestedCriteria);
var criteria = Session.CreateCriteria<Foo>("foo")
.Add(Subqueries.Exists(firstNestedCriteria)
.List<Foo>();
Does anyone know a workaround that doesn't involve using HQL?

I never had this problem, I usually use PropertyIn to join subqueries, but you can't always do the same.
In this particular case, you could fix it by using the property of the second query:
var secondNestedCriteria = DetachedCriteria.For<Baz>("baz")
.SetProjection(Projections.Id())
.Add(Restrictions.EqProperty("baz.FooName", "bar.FooName") // is equal to foo.Name
.Add(Restrictions.EqProperty("baz.BarName", "bar.Name");
If this doesn't help in your real case, you may ask for a solution of the real case. I don't think that there is a general solution.

Related

How to create where statement based on result of multiset

So, i would like to filter my query by exact match in result of multiset. Any ideas how to do it in JOOQ?
Example:
val result = dsl.select(
PLANT_PROTECTION_REGISTRATION.ID,
PLANT_PROTECTION_REGISTRATION.REGISTRATION_NUMBER,
PLANT_PROTECTION_REGISTRATION.PLANT_PROTECTION_ID,
multiset(
select(
PLANT_PROTECTION_APPLICATION.ORGANISM_ID,
PLANT_PROTECTION_APPLICATION.ORGANISM_TEXT
).from(PLANT_PROTECTION_APPLICATION)
.where(PLANT_PROTECTION_APPLICATION.REGISTRATION_ID.eq(PLANT_PROTECTION_REGISTRATION.ID))
).`as`("organisms")
).from(PLANT_PROTECTION_REGISTRATION)
// here i would like to filter my result only for records that their organisms contain specific
// organism id
.where("organisms.organism_id".contains(organismId))
I've explained the following answer more in depth in this blog post
About the MULTISET value constructor
The MULTISET value constructor operator is so powerful, we'd like to use it everywhere :) But the way it works is that it creates a correlated subquery, which produces a nested data structure, which is hard to further process in the same SQL statement. It's not impossible. You could create a derived table and then unnest the MULTISET again, but that would probably be quite unwieldy. I've shown an example using native PostgreSQL in that blog post
Alternative using MULTISET_AGG
If you're not nesting things much more deeply, how about using the lesser known and lesser hyped MULTISET_AGG alternative, instead? In your particular case, you could do:
// Using aliases to make things a bit more readable
val ppa = PLANT_PROTECTION_APPLICATION.as("ppa");
// Also, implicit join helps keep things more simple
val ppr = ppa.plantProtectionRegistration().as("ppr");
dsl.select(
ppr.ID,
ppr.REGISTRATION_NUMBER,
ppr.PLANT_PROTECTION_ID,
multisetAgg(ppa.ORGANISM_ID, ppa.ORGANISM_TEXT).`as`("organisms"))
.from(ppa)
.groupBy(
ppr.ID,
ppr.REGISTRATION_NUMBER,
ppr.PLANT_PROTECTION_ID)
// Retain only those groups which contain the desired ORGANISM_ID
.having(
boolOr(trueCondition())
.filterWhere(ppa.ORGANISM_ID.eq(organismId)))
.fetch()

Get common ManyToMany objects with django extra select

class Seller(object):
type = ...
name = ...
cars = models.ManyToManyField(Car)
class PotentialBuyer(object):
name = ...
cars = models.ManyToManyField(Car)
class Car(object):
extra_field = ...
extra_field2 = ...
Suppose I have a relationship like this. I would like to use extra queryset modifier to get the list of cars that are already been picked out by PotentialBuyers when I fetch a seller object. I suppose the query queryset will something like this.
def markPending(self)
return self.extra(select={'pending': 'select images from PotentialBuyer as t ...'})
How can I accomplish this? Is there a better way? I could fetch the seller object and the potential object and do sets, but I'd think it would be cleaner to make it handled by the database. I am using PostgreSQL 9.5.
I think the Exists subquery expression will do what you want. Or at least it'll get you started on the right path. Docs Or you might want to use an aggregate to count the number of them.
Edit: If you need to select the full objects rather than the count, existence or a single entity, then use a Prefetch instance in prefetch_related. https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.Prefetch
Not quite the answer, but this is the solution I ended up with and I am satisfied by the performance. Perhaps someone can answer the question later :
from api.models import PotentialBuyer
potentials = PotentialBuyer.objects.filter(owner=user_id, default=True).first().cars.all()
Car.objects.filter(....).annotate(pending=Case(When(id__in=potentials, then=Value(True)), default=Value(False), output_field=BooleanField()))

LINQ to SQL indirect variable

First, may I apologise if this question is too basic for this forum. I am very new to this and am struggling with a number of basics - but am persevering!
I have a problem in that I want to create a LINQ to SQL query with a WHERE clause with an indirect reference to one of the columns in my database. For example, if I had some code that looked something like this:
var PLMatches = from PLMat in db1.PLAccountHeaders
where PLMat.CompanyAlphaId.Equals(CoId)
&& dbField.Equals(Limit)
select PLMat;
such that dbField would be a variable containing the name of the database field. So, if the value of dbField was"PLMat.ItemCode" it would happily go away and return all instances of records with an ItemCode equal to the value of Limit and if value of dbField was"PLMat.ItemName" it would happily go away and return all instances of records with an ItemName equal to the value of Limit and so on.
I would really appreciate some help on this both to answer a very specific problem and I am sure it will enhance my basic understanding.
Many thanks
i dont think that what you are asking for is possible in LINQ, you can however use the Dynamic Linq Library.
here's the link
You download the zip, unzip it and then just reference it in your solution.
you can then do something like this:
// the "normal" LINQ way:
var query = from x in ctx.People
where x.city == "Boston" && x.age > 18
orderby x.ID
select x;
// the Dynamic Linq way:
var query = database.People
.Where("city = Boston AND age > 18")
.OrderBy("id")
.Select("New(Person as Name, Age)");
Another way (besides dynamic linq) is composing your query conditionally. Like so:
var PLMatches = from PLMat in db1.PLAccountHeaders
where PLMat.CompanyAlphaId.Equals(CoId)
select PLMat;
if (dbField == "ItemCode")
PLMatches = PLMatches.Where(m => m.ItemCode == Limit);
else if (dbField == "ItemName")
PLMatches = PLMatches.Where(m => m.ItemName == Limit);
else if (dbField == ...
The code looks a bit repetitive, but I always prefer to do it this way if the number of possible conditions is not too large. The advantages are, first, that the code integrity check is at compile time and not at runtime (as with dynamic linq) and, second, it is very clear what the code is about. (The second advantage also goes for dynamic linq, but less so for a third alternative: building expressions in code).
You can compose linq queries this way because of deferred execution. PLMatches = PLMatches.Where... only changes the query, but nothing is executed yet.

What is the best way to format long chained methods?

What is the best way to format code with chained methods? Especially if it goes on for a long time? If you have a chain of three or so, you can put it on one line, but it gets cumbersome after you have a lot and it makes debugging difficult.
FYI, I'm talking about this: http://en.wikipedia.org/wiki/Method_chaining
Sometimes I write code like this (in Java):
DetachedCriteria criteria = DetachedCriteria.forClass(Taskdsr.class);
criteria=criteria.add(someRestriction);
criteria=criteria.add(someOtherRestriction);
criteria=criteria.setFetchMode(Criteria.DISTINCT_ROOT_ENTITY);
in place of:
DetachedCriteria criteria = DetachedCriteria.forClass(Taskdsr.class).add(someRestriction).add(someOtherRestriction).setFetchMode(Criteria.DISTINCT_ROOT_ENTITY);
You can format it across multiple lines:
DetachedCriteria criteria = DetachedCriteria.forClass(Taskdsr.class)
.add(someRestriction)
.add(someOtherRestriction)
.setFetchMode(Criteria.DISTINCT_ROOT_ENTITY);

Nhibernate C# - Return only objects where string property is not null or empty

I'm writing a query using ICriteria that should return only the objects where property "Message" has value (i.e. is not null or empty). Below is the format I'm using.
ICriteria.Add(Restrictions.Not(Restrictions.Eq("Message", " "));
ICriteria.Add(Restrictions.Not(Restrictions.Eq("Message", String.Empty));
Can somebody help me with this? Thank you!
You might want something like:
ICriteria a = session.CreateCriteria(typeof(A));
a.add(Restrictions.Not(Restrictions.Eq("Message", " "));
a.add(Restrictions.Not(Restrictions.Eq("Message", string.Empty));
Although, your first one isn't really checking null, it's checking a single space.
I've not tried this, but it thnk the following should work:
ICriteria crit = session.CreateCriteria(typeof(theType))
.Add(Restrictions.IsNotNull("Message"))
.Add(Restrictions.IsNotEmpty("Message"));
Finally, I discovered the combination I was looking for!
lvCriteria.Add(Restrictions.Not(Expression.Eq("Msg", string.Empty)));
This combination of Restrictions and Expression works as expected; narrowing out all empty strings. I do not know why I could not achieve these results earlier even with:
lvCriteria.Add(Restrictions.Not(Restrictions.Eq("Msg", string.Empty)));
Thank you to all who tried.
What you really need is:
ICriteria crit = session.CreateCriteria(typeof(theType))
.Add(Restrictions.Not(Restrictions.Eq("Msg", string.Empty)))
.Add(Restrictions.IsNotNull("Msg"))
This is working fine for me and profiler shows correct SQL i.e. something like:
msg<>'' and msg is not null.
First answer did not work for me as Restrictions.IsNotEmpty/Empty applies only to collections (in NH 2.0.1 at least).