I have a general question about the interaction of linq with an entityquery and ria services. I know that within my domainconext I can define queries for my application. For example, I can use linq within my domaincontext to define the following query:
public IQueryable<User> GetUsersFriends(Guid usersID)
{
return (from f in this.ObjectContext.Friends join u in this.ObjectContext.Users on f.FriendUsersID equals u.ID where f.UsersID.Equals(usersID) select u);
}
This is all good. But my question is, can I perform the same type of query from the client side (silverlight app) ? So can I do build a linq statement against an EntityQuery object and return data from the database in this fashion?
I know that I can perform linq operations on the collections of entities that already have been loaded? Can I use linq on the client side to load the collections?
I am thinking that all queries that ultimately hit the database need to be defined in my domain context? Out of force of habit I keep trying to use linq to define new queries and pass those to the domaincontext.load() operation....which fails miserably. The domainconext probably doesn't have any way to marshal the queries across the line...right?
Is my understanding correct? If someone could help verify this for me, I would appreciate it.
One of the main advantages of IQueryable (and it's also a pretty good security risk), is that you CAN create a query on the client side, and serialize it back to the server for processing on the serve. The requirement here is that it must return the type that is defined (in your case IQueryable where User is the type that must returned in a collection that supports IEnumerable<>.
I took my example from Shawn Wildermuth (wildermuth.com), and tweaked it a little. This is what I use in my client side "model".
publicvoid PerformQuery<T>(EntityQuery<T> qry, EventHandler<EntityResultsArgs<T>> evt, object pUserState = null, bool NoRecordsThrow = False, LoadBehavior pLoadBehavior = LoadBehavior.MergeIntoCurrent ) where T : Entity
{
ModelDataContext.Load<T>(
qry,
pLoadBehavior,
r =>
{
if (evt != null)
{
try
{
if (r.HasError)
{
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif
//internal class to record error messages
AppMessages.ErrorMessage.Display(string.Concat(r.Error.Message, Environment.NewLine, "------------------------", "------- Stack Trace ------", Environment.NewLine, r.Error.StackTrace));
}
else if (r.Entities.Count() > 0 || NoRecordsThrow)
evt(this, new EntityResultsArgs<T>(r.Entities, r.UserState));
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif
evt(this, new EntityResultsArgs<T>(ex));
}
}
},
pUserState);
}
When I would then use it like this:
var UserQuery = <DomainServiceName>.Users.Where(pUser => pUsers.City == "Calgary");
PerformQuery<User>(UserQuery, UserQueryComplete)
The downside is that via this one endpoint, User data can be extracted with any kind of filter that is issued on the client side....
HTH, Richard