views:

595

answers:

2

I'm using ado.net data services and want to implement row level security in the query interceptor to limit the data to only return data that the user is allowed to see. The complexity comes in in that the user name for the the user is on another table. So I thought I could retrieve a list of events that the user can see according to the entry in the OnlineSubscription table for that user and then return whether the current event matches any entries that are returned as follows:

[QueryInterceptor("Events")]
public Expression<Func<Events, bool>> QueryEvents()
{

  var allowedEventList = (from os in context.OnlineSubscription
                          from e in os.Events
                         where os.UserName == HttpContext.Current.User.Identity.Name
                         select e;

return e => events.Intersect(new List<Events>
                                         {
                                                 e
                                         }).Any();
}

However this throws a "Not implemented" exception. So my question is: Is there a right way to compare the current entity to a list of entities in the query interceptor?

EDIT: I've also tried:

return e => events.Any(evnt => evnt.Event_Key == e.Event_Key);

without any success (once again getting the "Not implemented" exception).

+1  A: 

Apparently this fails because by using the lambda expression events.Any... it's already querying in the initial context (ie. querying on Events straight) and then when you add the events.Any clause it also tries to query on the new context (ie. the nested "from" of Events within OnlineSubscription) so it understandably throws an exception.

I then used:

[QueryInterceptor("Events")]
public Expression<Func<Events, bool>> QueryEvents()
{    
    return e => e.OnlineSubscription.Any(os => os.UserName == HttpContext.Current.User.Identity.Name);
}

Which works since this is just querying in the same context as the initial query and merely traverses through relationships.

James_2195
A: 

Really? I'm getting a "Not Implemented" exception with this code:

[QueryInterceptor("Products")]
public Expression<Func<Product, bool>> QueryProducts()
{
    return p => p.User.Username == HttpContext.Current.User.Identity.Name;
}

It works fine if I filter by a property on the Product object itself, but not via any of it's relationships.

Ok, found the problem. It needs to be like:string user = HttpContext.Current.User.Identity.Name;return p => p.User.Username == user;Instead and then it works. I guess it's just because ADO.NET Data Entity Model doesn't know how to translate the HttpContext reference as a parameter to be passed in while Linq to SQL does.

related questions