Uncertain of how to implement a specific extension to nHibernate with LINQ
In the blog post by the rather popular ayende.com website blog post .There is a section that catches my eye in a very specific manner.
Close to the end of the post, he makes a comment, quoted from the site
The answer that I give for things like "well, so how can I apply security filtering” is that you throw that into an extension method and do something like this:
var query =
(
from post in session.Query<Post>()
where post.DueDate > DateTime.Now
select post
)
.FilterAccordingToUserPermissions(CurrentUser)
开发者_StackOverflow .ToList();
I really like this approach, to be honest. It looks very clean to me. But in my inexperience and lack of knowledge of either Extension Methods or nHibernate one, I cannot seem to reproduce it.
var query = ( from post in session.Query<Post>() ...
this tells me the object being used is an NHibernate.Linq.Query<T>
object. I mainly use QueryOver<T>
in my projects for the purpose of projecting them to Futures
, but I digress...
I realize this is very ambiguous, and not at all a very consice request - but I was wondering if anyone would be willing to post a sample of how one might achieve this example code.
Here is what I do not understand;
- I do not understand how to extend the
Query<T>
orQueryOver<T>
object. - If I do extend the objects, I do not understand how to make that extension impact/filter the database lookup.
- If I am able to impact the database lookup, I do not understand how it will influence the performance.
- I do not really understand where the
CurrentUser
is coming from. It seems to me that it would require another database trip to get that, and that again goes against what nhprof and most of the books I've been reading keep telling me (don't make multiple trips for one operation).
point 3 is the one that baffles me the most. The only thing I can think of is that this method takes the query and runs it, then filters it, then returns the results. This seems counter-intuitive to me (and it seems against a lot of the things I have seen on the ayende.com/blog site, since it inheritly suggests a lot of non-essential database calls)
So there you have it. I'm pretty clueless, and I do understand that to some of you more experienced, this is a really stupid question. But I am much too new to understand everything and I've spent the better part of 5 weeks trying to do this.
Yes you are right, the question is a bit vague but I'll try to address your points.
1) You are not really extending the Query object. The extension that you would be writing would actually be against IQueryable so...
public static IQueryable<Post> MySecurityExtension(this IQueryable<Post> repository, string currentUser)
{
return repository.Where(p => p.User == currentUser);
}
Obviously your security criteria would be more complicated than this.
2) The extension method allows you to add additional criteria into the IQueryable that was passed in. That additional criteria is then built into sql by the NH Query engine when that queryable is executed.
3) Performance is obviously tied the query that you write, a more complex query will perform slower. However there is no performance hit from the extension method in and of itself. It is important to understand that the query is not executed until the entire query has been built. This is usually triggered by a .ToList(), Single(), First() or other statements that actually enumerate of the queryable.
4) CurrentUser comes from you and it may have to be fetched from the database beforehand. But you are probably going to have to do that anyways in your application.
The extension method has nothing really to do with NHibernate. It is simply used to filter (or "apply a security policy to") the IEnumerable<Post>
returned by the NHibernate query.
In other words, NHibernate will return a enumerable list of entities (from the database), and the extension method will filter that list. The implementation of FilterAccordingToUserPermissions
is not provided so we can't say much about it, including whether it will perform poorly or not.
The extension method would be defined in a static class, as follows:
public IEnumerable<Post> FilterAccordingToUserPermissions(this IEnumerable<post> list, CurrentUser user)
{
// implementation
}
And don't forget, there is no such thing as a stupid question :)
精彩评论