开发者

Linq query error

I am using following Linq query:

from p in People
 where p.Name == "George Luc开发者_开发技巧as"
select p.TitlesActedIn

where TitlesActedIn is a list. People and TitlesActedIn are associted

But I am getting error:

InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.PropertyExpression' to type 'System.Data.Services.Client.ResourceExpression'.

Please suggest solution.


A very simple way to do it:

var query = People
    .Expand("TitlesActedIn")
    .Where(p => p.Name == "George Lucas")
    .First()
    .TitlesActedIn.Select(t => t.ShortName);              
query.Dump();

Its important to note, that this will crash if the name you pass it does not exist. (The First Operator will throw an exception. You would need to either guarantee that the name exists, or do it in two steps.


If you want to do it in one step it comes down to this:(please note what is coming back)

http://odata.netflix.com/catalog/People()?$filter=Name eq 'George Lucas'&$top=1&$expand=TitlesActedIn

You need the expand or it will quit evaluating after the .First(), because TitlesActedIn will be empty.

It basically translates to select the Person, include (expand) the TitlesActedIn association, then select the name (client side)

The downside of this is that you are pulling back everything (all fields) from the Titles table. So for every title associated to the Person it is returning (Title, Year, Description, ShortName, etc).

If you did this in two queries you could only pull back "ShortName" from the TitlesActedIn association.


UPDATED: See this question and answer to understand the limitations on Select Many in Data Services + Another solution based on $expand (note this requires the server to support expand)

If this is WCF Data Services and TitlesActedIn is a collection of related movies. Then you can do this in one query only if Person.Name is the primary key.

To illustrate this:

var titles = from p in people
             where p.Name == "George Lucas"
             from m in p.TitlesActedIn
             select m;

Will do what you want but only if Name is the key of the Person entity, otherwise this is unsupported.

If Name is not the key one way to do this (today) is with two queries, something like this:

var key = (from p in people
          where p.Name == "George Lucas"
          select new {p.Id}).Single().Id;

var titles = from p in people
             where p.Id == key
             from m in p.TitlesActedIn
             select m;

Another option though would be do an expand:

var george = (from p in people.Expand("TitlesActedIn")
             where p.Name == "George Lucas"
             select p).Single();

var titles = george.TitlesActedIn;

But that relies on the server supporting $expand - which not all servers do...

Note we are currently working on adding any/all support to OData and WCF Data Services, once that is released you would be able to write:

var titles = from t in titles
             where t.Actors.Any(a => a.Name == "George Lucas")
             select t;

Hope this helps

Note: in the code that gets the key for George Lucas I create an anonymous type because today WCF Data Services doesn't support materializing primitives directly.


Interestingly, the following works:

from p in People
where p.Name == "George Lucas"
select new { p.TitlesActedIn }

as does this:

(from p in People
where p.Name == "George Lucas"
select new { p.TitlesActedIn }).First().TitlesActedIn

The WCF client automatically adds the expansion call in the URI translation:

http://odata.netflix.com/Catalog/People()?$filter=Name eq 'George Lucas'&$top=1&$expand=TitlesActedIn&$select=TitlesActedIn/*


I get a similar error if I use a group by clause along with the lambda expression to fetch data using WCF Data Service. I got to know that certain operations are not supported by WCF data services. Please make sure you are not using unsupported LINQ operations.

http://msdn.microsoft.com/en-us/library/ee622463.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜