Request Genres by MovieId using LINQ to Netflix OData - linq

I am trying to create a LINQ query to return genres by movieid. The LINQ works in LINQPAD4. Can someone help me with the proper syntax? I am getting the following errors:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?)
and
Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
Code:(note I have wrapped Title in the following line with parenthesis, but are actually brackets in my code.
public List(Genre) GetGenresByMovieId(string movieid)
{
var genres = from t in MovieCatalog.Titles
where t.Id == "BVlLx"
select t.Genres;
return genres.ToList();
}

The right query would look like
public IEnumerable<Genre> GetGenresByMovieId(string movieId)
{
return from title in ctx.Titles
from genre in title.Genres
where title.Id == "BVlLx"
select genre;
}
In the method call syntax, you need to use SelectMany, not Select, since the filter on titles returns a list of titles (which will always contain just one title, but the compiler doesn't know that) and so you want to "concatenate" all genres for each title in the results.
The return type is actually IQueryable, but if you only plan to enumerate over it, you can use IEnumerable, or call ToList() to force execution right there in the method (the way I wrote it the query would actually execute only once you try to enumerate it).

Your problem is your projection:
select new { Name = g.Name }
That is projecting the query into an anonymous type.
You need to project into the IQueryable you have declared (IQueryable<Genre>)
When working with LINQ queries, it's preferable to use implicitly-typed variables (var).
Also, not sure why you have that extra "from" in your query, you don't need that.
Something like this should work:
var genres = from t in MovieCatalog.Titles
where t.Id = "BVlLx"
select t.Genres;
return genres.ToList();
var genres should be typed to an IQueryable<Genre>.
That is assuming you want to return a collection of Genre objects.
If you just want the name, do this:
select t.Genres.Name
But that will return a collection of string objects (and var genres should be typed to an IQueryable<string>).
However, i have no idea about the NetFlix OData API, but that should get you on the right track.

Related

Building a dynamic anonymous type Select statement using Linq

//list is IEnumeable NOT IEnumerable<T>
var IEnumerable<object> = list.AsQueryable().Cast<object>().Select(x=> .........);
object actually has a POCO underlying Anonymous class e.g
AccountId,Name,SecretInfo
What I want in the select statement is
AccountId = x.GetType().GetProperty("AccountId").GetValue(x,null),
Name = x.GetType().GetProperty("Name").GetValue(x,null)
Also I want to hide the SecretInfo Column which I can pass as a hardcoded string "SecretInfo"
Basically the select list needs to be built up dynamically on the Anonymous type....
How can this be done....Any Linq punters out there who can help me?
The answer to your question relies on anonymous types. The following code is what you can use:
var result = list.AsQueryable().Cast<Info>().Select(x => new
{
AccountId = x.AccountId,
Name = x.Name
});
Between the brackets that follow the new keyword in the select statement, you are creating an anonymous type that will have two implicitly typed read-only fields (AccountId and Name). Hope this helps!
I would like to post this quote from the linked (no pun intended) article:
Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence. For more information about queries, see LINQ Query Expressions (C# Programming Guide).

querying a list - returns only one value

I have created a structure and list.
public struct CarMake
{
public string name;
public string id;
}
I added structure objects to this (carMakers) and am trying to query
string selCar = from c in carMakers
where c.name == selectedCarMfgName
select c.id;
I am getting an error near select statement- cannont implicity convert IEnumerable to string. I know that query returns only one value, that's why I have like that.
thanks !
string selCar = (from c in carMakers
where c.name == selectedCarMfgName
select c.id).SingleOrDefault();
Your query returns a collection (with one element). You should use Single() (or SingleOrDefault()) to get that one item. If the query can return more than one result, you should look into First() ( or FirstOrDefault())
Pay attention to the error message. It probably says something like
"cannot implicitly convert IEnumerable<string> to string."
The results of a query of a sequence is another sequence, an IEnumerable<T>. You may know that you expect only one result, but that's not what the query does. To obtain only one result, you can optionally include another extension method on the end.
yourQuery.First();
yourQuery.FirstOrDefault();
yourQuery.Single();
yourQuery.SingleOrDefault();
The difference in these is that the First* variations can work with sequenes with many elements, whereas the Single* variations will throw exceptions if more than one element is present. The *OrDefault variations support the concept of no matching elements, and returns the default value for the type (null in the case of classes, a default value (such as 0 for int) for structs).
Use the version that conforms to your expectation. If you expect one and only one match, prefer Single. If you only care about one out of arbitrarily many, prefer First.
carMakers.Add(new CarMake() { name = "Audi", id = "1234" });
string selCar =(from c in carMakers
where c.name == "Audi"
select c.id).FirstOrDefault();
Output- 1234
I would refactor my query slightly:
var selCar = carMakers.Single(c => c.name == selectedCarMfgName).id;
This assumes you know that the car is in the list. If not, use SingleOrDefault and check the return before getting the id.
I've not done too much with LINQ but because you are selecting into a string you may need to use FirstOrDefault as your statement could return back more than one value yet your string can only hold one.
First will return null value I think if nothing is found but FirstOrDefault will return you a blank string.

How to obtain property name and types (by reflexion or better) of a linq result anonymous type

I need to obtain property names and types of a linq result (by reflection or better)...
I say better because I think linq should have a structure in every query with this info!!!
for example
I have a linq query like:
dim query1 = from e0 in clients select new { e0.id, e0.name }
I pass query1 as a parameter to a function, then I need to know how much properties there are in query1, the property names and the property types...
Thx, ZEE ;)
Type memberType = query1.GetType().GetGenericArguments()[0];
foreach (var a in query1)
{
foreach (PropertyInfo pi in memberType.GetProperties())
{
Console.WriteLine(pi.GetValue(a, null));
}
}
actually I will store the PropertyInfos in a List<PropertyInfo> and in the inner foreach, use the stored properties. But the above code is the simplest to understand.
First, you shouldn't be passing query results typed as a sequence of instances of an anonymous type to another method. If you're doing this, you should make a concrete class for the query results.
You can use reflection to tear out the properties from query1 as follows. query1 will implement IEnumerable<T> for some unique type T. Once you have this type, you can call
type.GetProperties()
to get an enumeration of the anonymous type member names.

linq problem with distinct function

I am trying to bind distinct records to a dropdownlist. After I added distinct function of the linq query, it said "DataBinding: 'System.String' does not contain a property with the name 'Source'. " I can guarantee that that column name is 'Source'. Is that name lost when doing distinct search?
My backend code:
public IQueryable<string> GetAllSource()
{
PromotionDataContext dc = new PromotionDataContext(_connString);
var query = (from p in dc.Promotions
select p.Source).Distinct();
return query;
}
Frontend code:
PromotionDAL dal = new PromotionDAL();
ddl_Source.DataSource = dal.GetAllSource();
ddl_Source.DataTextField = "Source";
ddl_Source.DataValueField = "Source";
ddl_Source.DataBind();
Any one has a solution? Thank you in advance.
You're already selecting Source in the LINQ query, which is how the result is an IQueryable<string>. You're then also specifying Source as the property to find in each string in the databinding. Just take out the statements changing the DataTextField and DataValueField properties in databinding.
Alterantively you could remove the projection to p.Source from your query and return an IQueryable<Promotion> - but then you would get distinct promotions rather than distinct sources.
One other quick note - using query syntax isn't really helping you in your GetAllSources query. I'd just write this as:
public IQueryable<string> GetAllSource()
{
PromotionDataContext dc = new PromotionDataContext(_connString);
return dc.Promotions
.Select(p => p.Source)
.Distinct();
}
Query expressions are great for complicated queries, but when you've just got a single select or a where clause and a trivial projection, using the dot notation is simpler IMO.
You're trying to bind strings, not Promotion objects... and strings do not have Source property/field
Your method returns a set of strings, not a set of objects with properties.
If you really want to bind to a property name, you need a set of objects with properties (eg, by writing select new { Source = Source })

Return Datatype of Linq Query Result

I think I'm missing something really basic.
var signatures=from person in db.People
where person.Active==true
select new{person.ID, person.Lname, person.Fname};
This linq query works, but I have no idea how to return the results as a public method of a class.
Examples always seem to show returning the whole entity (like IQueryable<People>), but in this case I only want to return a subset as SomeKindOfList<int, string, string>. Since I can't use var, what do I use?
Thanks!
You can get concrete types out of a linq query, but in your case you are constructing anonymous types by using
select new{person.ID, person.Lname, person.Fname};
If instead, you coded a class called "Person", and did this:
select new Person(peson.ID, person.Lname, person.Fname);
Your linq result (signatures) can be of type IEnumerable<Person>, and that is a type that you can return from your function.
Example:
IEnumerable<Person> signatures = from person in db.People
where person.Active==true
select new Person(person.ID, person.Lname, person.Fname);

Resources