Print Page | Close Window

IEntityServerFetching - Which entities are we retrieving?

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2009
Forum Discription: For .NET 3.5
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=1335
Printed Date: 16-Apr-2024 at 3:30am


Topic: IEntityServerFetching - Which entities are we retrieving?
Posted By: jsobell
Subject: IEntityServerFetching - Which entities are we retrieving?
Date Posted: 18-Jun-2009 at 6:35am
Hi,
We have implemented our security in the IEntityServerFetching interceptor but have come up against a tricky situation.
When we devised our security structure using RIA, the MS based services gave us the underlying GetClient, GetOrder etc methods, and for any client Linq request those methods were always called, even if the query was a join of a '.Include("Orders")' style request.
In each method we would then append the query with the filter function to ensure the user only receives objects for which they have valid permissions.
In DevForce though the OnFetching method is only called once for any query, so although we may look at args.Query.QueryableTypeto find the entity type to filter, it is far more difficult to find any 'other' relationships in the query.
For example, if wesay something like
from c in dd.Customers.Include("Orders").ToList()
then we would have to add two filters to our query, one on Customers, one on Orders, but the option is not presented as it is in RIA unless we work out how to parse the Query tree and see which tables are referenced, then add individual .Where filters in conditional blocks to extend the query appropriately.
Do you have any suggestions as to how we might approach this?

Cheers,
  Jason



Replies:
Posted By: kimj
Date Posted: 19-Jun-2009 at 4:29pm
You don't want to go rooting around the expression tree, but you can add filters to a query for multiple entity types, the easiest way to do this is with the EntityQueryFilterCollection.  These filtered entities don't have to actually be used in the particular query, in which case that filter is ignored.  
 
Filters are not currently applied to additional types brought in via .Include, however.  We'll look at addressing this in an upcoming release.
 
Since we strive to be feature compatible with RIA Services, I'm curious about a couple of things you mention.  For one, I wasn't aware that you can use .Include from a client-side query in RIA.  Assuming instead that the .Include is coming from a server-side query method (for example from GetCustomers), I don't believe that the query method(s) for any other entity types in the query expression will be called (so in this example, a GetOrders method would not be called to filter the Included orders).  Can you help fill me in on what RIA Services provides here?


Posted By: jsobell
Date Posted: 21-Jun-2009 at 5:52pm
My RIA coding is now a little rusty (after switching mindsets to DevForce), but I seem to remember you use the [Include] attribute in the metadata partial class, and that forces eager fetching, and I think there was another method on the Linq statement.
Either way, the subsequent fetches were also directed through the GetX() methods, allowing true filtering at each level of the query tree, so whether you did 'from c in Customers() join o in Orders()' or simply 'from c in Customers().Include("orders"), the interception was still possible.
This is extremely important in any auditing or security system, so I'll be interested to see if the EntityQueryFilterCollection addresses the first example, but it is extremely important that the filters also apply against 'Included' relationships because this is effectively an eager fetch in the same way as any conventional left outer join.
If the syntax wasn't so awful for the outer joins we would use them in place of the Includes, so we may have to do this in the short term.

Are there any good reasons to not apply the filter collection to the Included elements? What are the conceptual differences between .Include and the tortuous left outer join in Linq?  Is there anything we should beware of?

Cheers,
 Jason


Posted By: kimj
Date Posted: 22-Jun-2009 at 9:29am
For the record, RIA Services requires both the IncludeAttribute and the .Include (server-side only) extension in order to do this query spanning.  We have not found, in current testing with the May Preview, that the corresponding Get method is called for "included" data, or joined data either.
 
I need to check with the experts, but I believe the reason the filter is not currently applied to the Included entities, and why it may be hard to do, is that the Entity Framework doesn't support this in their LINQ syntax.  A DevForce EntityQuery goes to EF to be executed.
 


Posted By: jsobell
Date Posted: 22-Jun-2009 at 7:00pm
I may have been mixing my technologies.  Astoria definately allows this per-entity type interception, and as the RIA and Astoria teams are merging I expect we will see the same thing once RIA is finalised.
Either way, it's a crucial requirement when you're providing client-side querying, as otherwise there is no practical intercept point in eager-loading to ensure the client is requesting only the data they have access to.
I wonder how Astoria do it, since they also sit on top of EF.
The EF preview for .Net 4 is released today, so I'm sure this will open up a whole new world of pain...

Cheers,
 Jason



Print Page | Close Window