New approach to dealing with query options in Linq

217 views
Skip to first unread message

Gunnar Liljas

unread,
Sep 27, 2015, 2:00:36 PM9/27/15
to nhibernate-development
Hi!

I just made a commit (not a pull request, I'm not sure it's quite ready) with a new approach to query options in Linq queries. Instead of dealing with results operators for things that are actually not a part of the query, I made an expression visitor that extracts the query options from the query AND removes them. The options are applied to the parsed query.


There was one major hurdle, and that was to omit these options if they occur in a subquery. Currently the visitor solves this (or does it?) by detecting when the first chain of Call expressions is done, but of course it would be more convenient to use Relinq for this. But that happens later in the chain than currently feasible.

It's more a proof of concept, so I would very much like some feedback.

/Gunnar

Alexander Zaytsev

unread,
Sep 28, 2015, 1:38:33 AM9/28/15
to nhibernate-...@googlegroups.com
Hi Gunnar,

This looks very good. I think this can be simplified if we omit these operations (cacheable, timeout, etc) from a query at all.

I think this can be done by casting inside these methods (as EF does sometimes) to the INHibernateQueriable (or similar interface) to set options.

What do you think?

Best Regards,
Alexander

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gunnar Liljas

unread,
Sep 28, 2015, 3:07:10 AM9/28/15
to nhibernate-development
Hmm...I didn't think of that approach. I guess that could work! Worth trying.

Thanks for replying.

/G

Michael Ketting

unread,
Sep 28, 2015, 3:34:36 AM9/28/15
to nhibernate-development
Hi Gunnar!

EntityFramework is going a similiar route with a QueryAnnotationResultOperator they use to collect the annotations.
https://github.com/aspnet/EntityFramework/blob/dev/src/EntityFramework.Core/Query/Internal/QueryAnnotationExtractor.cs

That's actually one of the ideas I'm thinking of adopting for re-linq's own SQLBackend, too. For now, the ResultOperators certainly are the easiest way to accomplish this.

Best regards, Michael


On Monday, September 28, 2015 at 7:38:33 AM UTC+2, Alexander Zaytsev wrote:
Hi Gunnar,

This looks very good. I think this can be simplified if we omit these operations (cacheable, timeout, etc) from a query at all.

I think this can be done by casting inside these methods (as EF does sometimes) to the INHibernateQueriable (or similar interface) to set options.

What do you think?

Best Regards,
Alexander
On Mon, Sep 28, 2015 at 2:00 AM, Gunnar Liljas wrote:
Hi!

I just made a commit (not a pull request, I'm not sure it's quite ready) with a new approach to query options in Linq queries. Instead of dealing with results operators for things that are actually not a part of the query, I made an expression visitor that extracts the query options from the query AND removes them. The options are applied to the parsed query.


There was one major hurdle, and that was to omit these options if they occur in a subquery. Currently the visitor solves this (or does it?) by detecting when the first chain of Call expressions is done, but of course it would be more convenient to use Relinq for this. But that happens later in the chain than currently feasible.

It's more a proof of concept, so I would very much like some feedback.

/Gunnar

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

Gunnar Liljas

unread,
Sep 28, 2015, 3:42:28 AM9/28/15
to nhibernate-development
OK, interesting. A similar idea but a different approach. It does remove the ResultOperators though, which is a fair compromise.

/G 

To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

Gunnar Liljas

unread,
Sep 28, 2015, 11:42:36 AM9/28/15
to nhibernate-development
So, to keep the momentum going, any favored paths forward? I don't mind the ResultOperators that much, as long as they are removed. They do however become part of the expression cache key, unless a specifically ignored during that process.

Also, it was encouraging to get a response to my question. I wish there was more activity (or at least more active communication) regarding NH core development. 

/G

Peter Schojer

unread,
Sep 29, 2015, 7:47:07 AM9/29/15
to nhibernate-development
That's the commit with the SetLockMode extension? I am already waiting for this one :-)

Does this additional patch also fixes the problem that setlockmode currently only works on selecting "full" objects?

See my comment on  the JIRA Ticket NH-2140 where the following query fails:
var result = (from e in db.Customers where e.CompanyName == "Corp" select e.CustomerId).SetLockMode(LockMode.Upgrade).ToList();
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

Gunnar Liljas

unread,
Sep 29, 2015, 5:16:19 PM9/29/15
to nhibernate-development
It does come with a SetLockMode extension, yes. No, it does not fix that, nor do I think it should. If locking in combination with projection should work, I think the best syntax would be 

var result = (from e in db.Customers.WithLockMode(LockMode.Upgrade) where e.CompanyName == "Corp" select e.CustomerId).ToList();

But it doesn't work, not even with HQL or Criteria, and implementing it would be slightly tricky, since the only lockmode making any sense in such a scenario is LockMode.Upgrade (I guess). A separate JIRA issue, perhaps?

/G

To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

Peter Schojer

unread,
Sep 30, 2015, 1:14:04 AM9/30/15
to nhibernate-development
Yes,
your proposed syntax is closer to what the database generates, that would make more sense.
there is already a similar JIRA issue but for criteria: NH-1968

Maybe simply update that ticket?
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-development+unsub...@googlegroups.com.

Gunnar Liljas

unread,
Sep 30, 2015, 3:26:34 AM9/30/15
to nhibernate-...@googlegroups.com
Do that. As the discussion there indicates, it's not a simple issue.


Sent from Mailbox


To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhibernate-develo...@googlegroups.com.

Daniel Laberge

unread,
Feb 2, 2016, 2:58:51 PM2/2/16
to nhibernate-development
Hi,

This looks promising and might be the groundwork for a feature we're desperate for Query Hints.

As it stands, we had to disable the Parameter Sniffing feature in SQL Server to work around some queries timing out due to bad Query Plans.
This is far from ideal and other queries suffer due to this.

This is a concrete example of what we need to do:

Session.Query<SomeEntity>()
  
.Where(...)
  
.Select(...)
  
.QueryHint(JoinType.Hash)
  
.ToList();

// The generated SQL would look like this:
SELECT ...
FROM Project INNER JOIN
        OrganizationProject ON Project.ProjectID = OrganizationProject.ProjectID
WHERE   ...
OPTION (HASH JOIN)
 

My questions to you, Gunnar are: 
  • Have you made more progress on your implementation?
  • Would you be willing to add support for these Query Hints (OPTION MERGE JOIN, HASH JOIN) and optionally (LOOP JOIN, OPTIMIZE FOR UNKNOWN)?
If not, I would like to give it a shot (our backs are pressed against the wall and we need a solution soon), but I'm not familiar with this part of the NHibernate code base and would probably require some guidance on how best to implement this.

Thank you for your time and consideration.

--
Daniel.
Reply all
Reply to author
Forward
0 new messages