Filtering With EF 6 - linq

I have a method that is returning an IEnumerable of Materials
public IEnumerable<Materials> ListMyMaterials(int organization)
I want to filter it in the controller to only return Materials that are found in a Product that is made by the organization id passed in.
Here is my query:
return db.Materials.
Include("Organization").
Include("ProductMaterial.Product.Organization").
.Where(o => o.ProductMaterial.Select(p => p.Product.Organization.ID == organization)).AsQueryable();
The two errors I am recieving are:
1) Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'bool'
2) Cannot convert lambda expression to delegate type 'System.Func<{}.Models.Materials,int,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type
I dont have any problems filtering like this if the property had been on Materials, but I only want materials that are found in a products the Organization owns.
What is the proper way to filter the returned data set using a property found in related objects?

Instead of doing a complex Include in your above Lambda expression you can write a simple LINQ query to result as::
(from mat in db.Materials
join org in db.Organization on mat.OrganizationID equals org.ID
where mat.OrganazationID=organization
select new Material{
ID=mat.ID,
OrganizationID=mat.OrganizationID
})
I dont have any information of table schema that's why in my above LINQ query I have done join by considering OrganizationID as a joining Key.
Here your return Type will be IQueryable<Material>

It is because this expression:
.Where(o => o.ProductMaterial.Select(p => p.Product.Organization.ID == organization))
Does not evaluate to true or false. That select statement is a subquery and not a boolean condition

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).

How do I filter in linq query when field needs parsing first?

I have a data table containing multiple columns and one column that stores somewhat complex text patterns - I need to parse the field to determine if a particular sub strings exist in specific positions within the larger string pattern and then if the record should be filtered out as a result.
I can't see a way to perform the parse other than by writing a C# parsing function with String.Split method calls, foreach, etc. But if I try to parse like this:
var myFilteredTable = _db.MyTable.Where(t => t.Column1 == 'Filter1'
&& ParseIsMyItemInColumn2(t) );
I get "has no supported translation to SQL" errors.
The other option I thought of was to build the initial result without the Parse:
var myFilteredTable = _db.MyTable.Where(t => t.Column1 == 'Filter1' );
and iterate through the IQueryable resultset, testing each row with the parse function, to filter out the unwanted rows, but IQueryable does not have Remove function to strip out unwanted rows nor Add function to allow me to build up a new resultset.
So how can I filter in linq when I also need to write a Parse function?
Well the "initial filter in the database then do the rest locally" is easy:
var filtered = _db.MyTable.Where(t => t.Column1 == "Filter1")
.AsEnumerable() // Do the rest locally
.Where(t => ParseIsMyItemInColumn2(t));
AsEnumerable is a simple pass through method, but because the result is typed as IEnumerable<T> rather than IQueryable<T>, the subsequent LINQ operations use the LINQ to Objects methods in Enumerable rather than the ones in Queryable.
Obviously if a lot of items match the first filter but fail the second, that won't be terribly efficient...
Unfortunately, if the "parse function" is not something that can be translated to SQL, you will need to pull the results and use LINQ to Objects:
var myFilteredTable = _db.MyTable.Where(t => t.Column1 == 'Filter1')
.AsEnumerable().Where(ParseIsMyItemInColumn2);
Note that this will stream all of the results into memory, and then perform your parse.

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 })

Request Genres by MovieId using LINQ to Netflix OData

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.

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