LINQ method syntax
var methodSyntax = VersionControls.Where(x => !x.Removed).Max(x => x.VersionID);
LINQ query syntax
var querySyntax = from x in VersionControls
where !x.Removed
// how to do Max Aggregation in LINQ query syntax???
select x;
MSDN documentation says about Query Syntax and Method Syntax in LINQ
Query syntax and method syntax are semantically identical, but many people find query syntax simpler and easier to read. Some queries must be expressed as method calls. For example, you must use a method call to express a query that retrieves the number of elements that match a specified condition. You also must use a method call for a query that retrieves the element that has the maximum value in a source sequence.
Query syntax can't express everything that method syntax can
check how to combine them for Min and Max in this answer
var mixedSyntax = (from x in VersionControls
where !x.Removed
select x).Max(x => x.VersionID);
You have to keep in mind that the Max() method will throw an exception whenever the source collection is empty. That's why I would chain a DefaultIfEmpty(defaultElementValue) just before the Max() for safety issues. This way, ASh's solution would become :
var mixedSyntax = (from x in VersionControls
where !x.Removed
select x).DefaultIfEmpty(defaultVersionControlObject)
.Max(x => x.VersionID);
Related
I've searched through numerous examples on how to filter collection based on another collection and I have found an easy way, like so:
var oShipnotes = await DbContext.ShipNotes.Where(s => oManageRouteDto.ShipNotes.Any(mr => mr.Id == s.Id)).ToListAsync();
however it throws an exception that says it cannot be translated to SQL query.
Could anyone point me the right direction how to solve this?
Thanks!
Replace nested LINQ query to materialized list of identifiers:
// 1) get the list of target ship note identifiers
var ids = oManageRouteDto.ShipNotes.Select(mr => mr.Id).ToList();
// 2) pass this list into Where using Contains
var oShipnotes = await DbContext.ShipNotes.Where(s => ids.Contains(s.Id)).ToListAsync();
EF is aware of this pattern and translates IList<T>.Contains into SQL's IN condition.
Since EF deals with IQueryables, each LINQ query must be translated into valid SQL expression. As a result, EF and underlying provider cannot translate every valid LINQ query (from C# perspective) just because SQL is not C#.
I would like to retrieve a list of values from a SQL table where the records start with a prefix defined in another table.
This post gives an accurate answer, but it is for EF and not Linq to SQL.
With SQL I get an error:
Only arguments that can be evaluated on the client are supported for
the String.Contains method
Sample code:
var lookupList = dc.LookupTable.Select(p => p.Prefix);
var q = dc.Personnel
.Where(item => lookupList
.Any(p => item.Surname.StartsWith(p))).Select(x => x.PersonID);
This works with EF. Yes, I can ToList() my collections but the tables are big and the query becomes very slow. Any suggestions on how to make it work without enumerating my objects?
This part: .Any(p => item.Surname.StartsWith(p)) gives the error:
Only arguments that can be evaluated on the client are supported for the String.Contains method
It tells you Contains method does not work with the given parameter which can only be evaluated on the server. StartsWith basically uses the same mechanism.
So, instead of Contains or StartsWith you should use IndexOf to find out whether or not the containing parameter is occured at the beginning or not:
.Any(p => item.Surname.IndexOf(p) == 0)
According to MSDN:
IndexOf(T):
The index of item if found in the list; otherwise, -1.
This answer is partially taken from here.
I am working on a Linq query expression statement, and want to use a let statement to set a constant value as part of the query to reduce potential errors.
In my example... (this is total mock up). the let statement "validateCount" is the question.
from referenceRow in context.SomeTable
// We want 8 in the Take and the results to still be 8 after the where.
// instead of typing in the value twice (in this example), i wanted to use a constant value here
let validateCount = 8
// sub query expression in my example
let subQuery = from sub in context.SomeTable
where sub.SomeColumn == rowReference.SomeColumn
orderby sub.SomeColumn descending
select sub
// use the sub query, take X amount, apply filter, check to see if Count() is the same as Take()
where subQuery.Take(validateCount) // this is where we fail. if we put in the constant 8, we are ok.
.Where(x => x.SomeOtherColumn == "Some value")
.Count() == validateCount // this is fine
select referenceRow
Unfortunately it seems that the let expression "validateCount" which has a single value of 8 in this example, can only work in the comparison part of .Count() but cannot be passed into the .Take() without throwing an exception.
Limit must be a DbConstantExpression or a DbParameterReferenceExpression.
Parameter name: count
Looking for a solution to use some user-defined constant in a single code location that can be used in the rest of the query expression, both in the .Take() and .Count() without having to be updated several spots in the code.
our application allows users to supply their own linq query expression to build their queries. I can't define anything outside the scope of this query, and must be within, using something like a 'let' statement.
let statement generates intermediate anonymous type projection (Select call) in the query expression tree. EF query provider (as indicated by the exception message) requires Skip and Take arguments to be resolved to constant or variable values (i.e. to be able to be evaluated locally), hence the let cannot be used for that purpose.
Instead, the constants/variables used in Skip / Take expressions should be defined outside of the query and used inside.
To define a constant value you would use:
const int validateCount = 8;
var query = (from .... Take(validateCount) ...);
To define a variable value (SQL query parameter):
int validateCount = 8;
var query = (from .... Take(validateCount) ...);
Here the C# compiler will turn validateCount into closure and EF query provider will be happy to bind a parameter (with that value).
our application allows users to supply their own linq query expression to build their queries. I can't define anything outside the scope of this query, and must be within, using something like a 'let' statement.
When supplying their own queries, the users should follow the same Skip / Take argument rules as above, i.e. define their constants and variables outside of their queries.
This is my code:
string queryString = "Marco".ToLower();
utenti = db.User.Where(p =>
queryString.Contains(p.Nickname.ToLower()) ||
queryString.Contains(p.Nome.ToLower()) ||
queryString.Contains(p.Cognome.ToLower())).ToList();
but I get:
Only arguments that can be evaluated on the client are supported for the String.Contains method.
Why? Can't I use .Contains()?
Try .IndexOf. It is not LINQ that can't do Contains, it's LINQ to Entities and LINQ to SQL that can't.
string queryString = "Marco";
utenti = db.User.Where(p =>
queryString.IndexOf(p.Nickname, StringComparison.OrdinalIgnoreCase) >= 0 ||
queryString.IndexOf(p.Nome, StringComparison.OrdinalIgnoreCase) >= 0 ||
queryString.IndexOf(p.Cognom, StringComparison.OrdinalIgnoreCasee) >= 0)
.ToList();
Why?
LINQ uses deferred execution. This means it waits until you want to iterate over your query results before it does anything. There are 3 main types of LINQ:
LINQ to Objects - when your IEnumerable is already on the heap.
LINQ to Entities - when you want to query a database using Entity Framework.
LINQ to SQL - when you want to query a database using LINQ to SQL.
Deferred execution in the context of the second 2 means that your query is not executed on the database until you enumerate the results in a foreach block, or invoke an enumeration method like .ToList, .ToArray, etc. Until then, your query is just stored as expression trees in memory.
Your query would work just peachy if db.User was a collection in memory. However when the data is in a database, LINQ to Entities (or LINQ to SQL) must translate your expression trees to what it calls a "store expression" -- which is just fancy talk for "convert my LINQ expressions to SQL".
Now imagine you had a custom C# algorithm you wanted to use for your query, and you did something like this:
var result = db.User.Where(x => MyCustomMethod(x));
There is no way today that LINQ to Entities can convert your C# code into a SQL query (store expression). It is the same with a lot of other C# methods you rely on daily. It also does not support .ToLower, .ToUpper, .StartsWith, .EndsWith, etc. There is a limited number of C# methods that can be converted to store expressions, and .IndexOf just happens to be one of them.
However keep in mind that it is only the string object's Contains method that we are talking about here that is not supported for store expressions. LINQ to Entities does support .Contains on IEnumerables. The following is valid and will work with LINQ to Entities (not sure about LINQ to SQL):
var idsIWantToFind = new[] { 1, 2, 3 };
var users = db.Where(x => idsIWantToFind.Contains(x.UserId));
The above is the equivalent of doing a SQL WHERE UserId IN (1, 2, 3) predicate.
I'm using Entity Framework in my ASP.NET, C#, Web Application. If I need to select a record from DataBase (in Data Access Layer), which method should I use? Linq query or a Lambda Expression?
Eg:-
//Linq
var result = from a in db.myTable.Take(1) where a.Id == varId select a;
return result.First();
//Lambda
return db.myTable.FirstOrDefault(a => a.Id == varId);
Is there any preferred way in this scenario or any advantage over the other?
Query Expression compiles into Method Expression (Lambda expression), so there shouldn't be any difference, In your code though you are accessing First and FirstOrDefault which would behave differently.
See: Query Syntax and Method Syntax in LINQ (C#)
and LINQ Query Expressions (C# Programming Guide)
At compile time, query expressions are converted to Standard Query
Operator method calls according to the rules set forth in the C#
specification. Any query that can be expressed by using query syntax
can also be expressed by using method syntax. However, in most cases
query syntax is more readable and concise.
Linq query syntax is just a syntax sugar for expression methods. Any Linq query compiled into expression methods. Btw your first query:
var query = from a in db.myTable.Take(1)
where a.Id == varId
select a;
return query.First();
Is equivalent to
return db.myTable.Take(1).Where(a => a.Id == varId).First();
Both of your tries use Linq.
The first takes one record and checks if the id matches.
The second takes the first record where the id matches.
That's a difference.
Every query expression can be expressed as C#-code using calls to query operators as extension methods. But the opposite is not true; only a small subset of the standard query operators can be used as keywords in query expressions. In other words query expressions have some limitations that the method-call mechanism does not have:
Some query operators have simply no C# query expression equivalent, e.g. ToArray().
We can't use all kinds of overloads in C#'s query expressions. E.g. there is an overload of Select() that awaits the index of the currently iterated object; you cannot call this overload within a query expression.
We can't use statement lambdas in query expressions. - This is the cause why object and collection initializers have been introduced into the C# language.
I guess the result is the same. Lambda is just a bit more comfortable.
If you need a result of just one table, the lambda expression is very fast and readable.