Generic Linq IN sub query expression - c#

I am trying to find a way to create the Linq Expression tree for a sub-query in-clause.
SELECT * FROM x WHERE X.Id IN (SELECT XId FROM Y)
Say I have this query, I need a way to create the System.Linq.Expression of the where clause. I have a generic repository base solution for numerous Entities and I am creating the expression tree dynamically for other filters and I would like to add this to the already created expression tree.
I know I can do something like below, but it isn't generic enough.
var xIds = Y.Select(x => x.XId).ToList();
var final = X.Where(x => xIds.Contains(x.Id)).ToList();
But I need Expression tree that this would create.
I played around with this link: Creating a Linq expression dynamically containing a subquery and it doesn't seem to work. I might be missing something though, been staring at this for a while.
Thanks!

Related

Meaning of OrderBy(x => 1) in C# LINQ

I encountered a linq expression that goes something like this:
var result = someCollection.Where(some_filter_condition).OrderBy(x => 1).ToList();
I'm wondering what's the purpose of the lambda expression x => 1 in the OrderBy linq method?
It seems pretty meaningless to me. It's going to "sort" the sequence, but instead of basing the sort order on a property of each element, it's going to use the key 1 for every element. This would be the same as not sorting at all.
I would guess that this was a placeholder that someone meant to go back and implement, but never did.
It is possible that some method would require input of type IOrderedQuery, so in order to convert it to required type, user might have added this lambda.

Expression Tree Multiple Entities

I am building an advanced search feature using Linq to entities and an expression tree. I have two entities, Entity A and Entity B where A is the parent and has a one to many relationship with B.
I have the expression tree for the fields in Entity A completed and the Linq query works as expected. What I'm trying to add is a feature where I can query to return Entity A records where a field in Entity B contains some text.
I've found enough hints out there to be fairly sure I can do this, but I'm trying to make it all into one tree so I can cumulatively filter. So I want to be able to say, more or less:
SELECT *
FROM EntityA EA
WHERE EA.FieldA = 'exampleinsql'
AND 'test' in (SELECT EB.FieldB
FROM EntityB EB
WHERE EntityB.EntityAForeignKey = EA.ID)
if that makes sense?
What I am doing currently is passing a list of filter objects and then combining a bunch of Expressions together using the below code snippits:
Expression expBody = ParseOperator(
Expression.Property(pe, filtersList.FirstOrDefault().FieldName),
filtersList.FirstOrDefault().Operator,
Expression.Constant(filtersList.FirstOrDefault().GetTypedValue()));
expBody = Expression.AndAlso(expBody, newExp);
As I mention, this works great for columns on the main entity. My understanding is that for EntityB I need to create a Lambda expression to add to this. Am I on the right track? Anyone got any ideas?
You have no need to manipulate expressions at all. Just use regular lambdas to write a query like this:
var query = from a in context.EntityA
where a.FieldA == "exampleinsql" &&
context.EntityB.Where(b => b.EntityAForeignKey == a.ID)
.Select(b => b.FieldB)
.Contains("test")
select a;
Of course, you could alternatively just do a Join for a query like this.

LINQ to SQL: lambda expression vs .Where() [duplicate]

This question already has answers here:
Extension methods syntax vs query syntax
(7 answers)
Closed 8 years ago.
Are
var movies = from m in db.Movies
select m;
movies = movies.Where(s => s.Title.Contains(searchString));
and
var movies = from m in db.Movies
where String.Equals(m.Title,searchString)
select m;
equivalent? And if so, why use one over the other? The syntax of the former seems more cryptic than the latter.
Behind the scenes, there's some translations going on.
For LINQ to SQL (and LINQ to Entities), the select keyword effectively ends a query. So, the second example has the filter as part of the SQL query, while the first one executes after the query.
There's a third way to do a LINQ query, called fluent syntax:
var movies = db.Movies.Where(s => s.Title.Contains(searchString));
If you look at the signature of Where, you'd find this:
IQueryable<T> Where(IQueryable<T> source, Expression<Func<T,bool>> predicate);
The key thing is the type of predicate: it's an expression of a (lambda) function, rather than merely a (lambda) function. This lets .Net dynamically convert the Expression object to SQL. For the query syntax, this parsing ends at select.
query expressions are compiled to method syntax by compiler when you compile the code,
whichever way you write code is a matter of preference, query expressions are preferred by developers from sql background.. :)
You're right, the latter form is more readable but sometimes you need the expression methods, like when you want to get the Count of result, and of course you can mix these two.

Convert IQueryable<T> or LINQ query to unique string

I have some LINQ query (or IQueryable<T> object based on LINQ query) and want to get some unique string based on this query.
I have, for example:
var someValue = 10;
var query = (from i in db.Customers
where i.Id == someValue
select i).AsQueryable();
I should get something like this:
"from i in db.Customers where i.Id == 10"
I am trying to use Expression object and play with it but I can not get generic approach to get string with exact parameters values.
E.g.:
public string GetKey<T>(IQueryable<T> query)
{
...
return unique_string;
}
Note that different parameters values for the same LINQ query should provide different strings.
Thanks in advance.
I strongly suspect that this is simply not going to work. Aside from anything else, if you have to use AsQueryable (i.e. if your original query is over IEnumerable<T> then the compiler will have used delegates instead of expression trees to start with.
If it's a pure IQuerable<T> all the way, you could try using query.Expression.ToString(), but frankly it's not something I'd want to rely on.
Solved this issue with Expression Tree Serialization with some improvements for getting exact values of passed parameters. It provides a big but unique XML file based on IQueryable objects.

Linq2Entities, many to many and dynamic where clause

I'm fairly new to Linq and struggling using dynamic where over a many to many relationship.
Database tables are like so:
Products <-> Products_SubCategories <-> SubCategories
with Products_SubCategories being a link table.
My full linq statement is
db.Products.Where("it.SubCategories.SubCategoryID = 2")
.Include("SubCategories")
.OrderBy(searchOrderBy)
.Skip(currentPage * pageSize)
.Take(pageSize)
.ToList()
.ForEach(p => AddResultItem(items, p));
So ignoring everything bar the Where() I'm just trying to pull out all products which are linked to sub category ID 2, this fails with
To extract properties out of collections, you must use a sub-query to iterate over the collection., near multipart identifier, line 8, column 1.
I think using the SQL-esque syntax I can do a subquery as per this link. However I'm not sure how to do that in the lambda / chaining syntax.
This is the start of a search function and I would like to build up the where string dynamically, as I have with the searchOrderBy string to avoid a large SELECT CASE. Products is linked to another table via a link table that I will need to include once I understand how to do this example.
Any help would be much appreciated!
Thanks
This is wrong:
db.Products.Where("it.SubCategories.SubCategoryID = 2")
SubCategories is a list. It does not have a property called SubCategoryID. Rather, it contains a group of entities which each have a property called SubCategoryID. That's a critical distinction.
When you run into a situation where you don't know how to proceed in there are multiple problems, it is good to break the problem down into several, smaller problems.
Let's start by removing the dynamic query. It will be easier to solve the problem with a non-dynamic query. Once you've done that, you can go back and make it dynamic again.
So start by using the non-dynamic syntax. Type something like this in Visual Studio, and see what IntelliSense does for you:
db.Products.Where(p => p.SubCategories.
You will quickly see that there is no SubCategoryID property. Instead, you will see a bunch of LINQ API methods for working with lists. If you know LINQ well, you will recognize that the Any() method is what you want here:
db.Products.Where(p => p.SubCategories.Any(sc => sc.SubCategoryID == 2))
Go ahead and run that query. Does it work? If so, you can move ahead to making it dynamic. I'm no ESQL expert, but I'd start with something along the lines of:
db.Products.Where("EXISTS(SELECT SC FROM it.SubCategories AS SC WHERE SC.SubCategoryID = 2");
As an aside, I use MS Dynamic Query ("Dynamic LINQ") for this sort of thing rather than Query Builder, as it's more testable.
It worked for me.
db.Products.Where("SubCategories.Any(SubCategoryID = 2)")

Categories