Related
I am getting an InvalidOperationException when using a projection into a record type (.Net 7). The query works fine if the where clause is chained. It also works if where clause is not chained and the projection is not into a record (class, anonymous type both ok).
public record TestDto(
int CellLocationId,
string AreaCode
);
This works - Chained:
var query = _context.myTable.Where(x => x.AreaCode == areaCode).Select(s => new TestDto(s.CellLocationId, s.AreaCode));
This fails - Unchained with record:
var query = _context.myTable.Select(s => new TestDto(s.CellLocationId, s.AreaCode));
query = query.Where(x => x.AreaCode == areaCode);
This works - Unchained with anonymous type:
var query = _context.myTable.Select(s => new {s.CellLocationId, s.AreaCode});
query = query.Where(x => x.AreaCode == areaCode);
When projecting into a record the sql shown in the error appears as:
System.InvalidOperationException: The LINQ expression 'DbSet().Where(v => new TestDto(v.CellLocationId, v.AreaCode).AreaCode == __areaCode_0)' could not be translated.
Why can I not use a record when my IQueryable is using an unchained where clause?
15/11/2022 Update.
Github issue
Possible workarounds - project into class, anonymous type or as per Bagus Tesa answer (and my preferred option) project into record type at end of statement.
About IEnumerable and IQueryable
IQueryable extends IEnumerable
IEnumerable most of the time works in memory, with some exceptions
IQueryable will be translated into SQL Query
Both IQueryable and IEnumerable execution are delayed until they are materialized (e.g. using ToList, AsEnumerable on IQueryable, etc.)
The API is designed this way for convenience in working with database queries. It allows (somewhat) interchangeable linq chains between the two. However, there are some caveats that need to be kept in mind.
IQueryable can only infer whats within its Expression. You can't for example do something like this:
public int GetAge(DateTime date)
{
...
}
var firstUserAge = _context.users.First().Select(q => GetDate(q.DoY));
It won't work, see QA. Linq is simply unable to translate the GetDate method into SQL Query.
The Problem
Let's take a look with the third case (anonymous class).
var query = _context.myTable
.Select(s => new {s.CellLocationId, s.AreaCode});
query = query.Where(x => x.AreaCode == areaCode);
Up to _context.MyTable the only known type is simply DbSet<myTable>. However, as it reach the Select(s => ...) it became aware of the anonymous type. Linq the consider that query should be an IQueryable<..__AnonymousType..>. Given the complete information is given to it. Linq can translate it into (roughly) sql query shown below and the result snuggly fits the anonymous type.
select s.cellLocationId, s.AreaCode
from myTable as s
where s.AreaCode = ....
Now, let's see what happens in the first case which surprisingly works.
var query = _context.myTable
.Select(s => new TestDto(s.CellLocationId, s.AreaCode))
.Where(x => x.AreaCode == areaCode);
Hang on a second! Did not I previously mentioned that you can't call a method on your program's side from within an IQueryable?
Yes, your code above won't work in the past, see discussion. You can find numerous examples of similar problem. You can also see examples on EF Core 7 documentation that they used anonymous types all the time. The microsoft's official tutorial on DTO also assigns properties manually one-by-one without using constructor.
However, EF Core 7 is pretty new. It is said to have better performance compared to earlier EF Core. The changes may involve reworks on how it materialize IQueryable. There are plenty of issues need to be sorted out.
You should run query intercepts and see the queries being feed into the database to see the difference between the two cases above. I'd bet that the first case actually fetch everything in myTable.
What We Should Do
We can simply map into DTO at a later part of the code (at the very end of the chain).
var query = _context.MyTable;
if(someFlag)
{
query = query.Where(s => s.AreaCode = areaCode);
}
//... a bunch more filters
return query.AsEnumerable()
.Select(s => new TestDto(s.CellLocationId, s.AreaCode));
This way, you can avoid the bug altogether while keeping most of the heavy-lifting on the database.
You may complain "I will have duplicate code for computing AreaCode." You have to remember, DTO in the first place does not contain business logic.
Regarding what Bagus Tesa wrote, the most important parts there are:
However, EF Core 7 is pretty new. It is said to have better performance compared to earlier EF Core. The changes may involve reworks on how it materialize IQueryable. There are plenty of issues need to be sorted out.
and
We can simply map into DTO at a later part of the code (at the very end of the chain).
I do not like how that answer is written, and I started writing my own, and then, frankly, I ended up with my own wall of text, and I don't like it just the same as their answer. Oh well. Maybe someone finds it useful. I mark it with community-wiki, because I don't really want to compete. It's more like, IDK, addendum?
Regarding the latter point, there have been some issues with early-selects since the dawn of EF. Select-as-custom-class is a special construct designed to allow your query to return your custom entity types (instead of anon bags of fields), especially in cases where you Join several tables, where the result cannot be simply the context.table you start the query from.
Thanks to how IQueryable is designed, you can moreless put such a .Select anywhere in your query, but there's a catch: once IQueryable is now <of-you-custom-type>, your custom properties are exposed instead of original tables columns, and it gets increasingly harder to guarantee that your code doesn't try to map/execute something untranslatable.
For example, imagine:
// case1:
var result = context.myTable
.Where(x => x.AreaCode == areaCode)
.Select<MyClass>(...)
.ToList();
// case2:
var result = context.myTable
.Select<MyClass>(...)
.Where(x => x.AreaCode == areaCode)
.ToList();
In the first case, it's obvious. AreaCode is a column from MyTable, defined by whatever type of MyTable.
In second case, it's AreaCode but from MyClass, and since someone wanted to introduce a new type, we can assume it's not mapped in EF mappings to the same table as MyTable. So if EF hanles that, it may have to so some guessing what MyClass.AreaCode really is.
Furthermore, what if MyClass.AreaCode was:
private string theCode = "5";
public string AreaCode {
set { theCode = value; }
get { return theCode + "1"; }
}
In that case, case1 would still function properly. And case2 can never function properly. Not even mentioning, custom class constructors, we write .Select(.. => new MyClas(...)) and it's very tempting to hide some custom logic into the ctor, even if it's as simple as if/throw/ ArgumentNullException.
If EF handles such cases it in ANY way (like: assume props/ctors are transparent, ignoring logic inside), results will be unintuitive to the programmer: MyClass used in Query will behave differently than MyClass used in the runtime. EF shouldn't handle it, it should throw, but determining that a getter or constructor is pass-through without custom logic isn't that easy.
That's why anon-types new {foo=, bar=} are always preferred (2) as the intermediate types - they are 100% compiler-generated, the compiler knows everything about them, the compiler knows all fields/properties are plain and transparent, and that's why it's not a huge problem if you put .Select<anon> even early in the LINQ query. (1)
But let's get back to your code.
In that record-related code samples you provided:
// first:
var query = _context.myTable
.Select(s => new TestDto(s.CellLocationId, s.AreaCode))
.Where(x => x.AreaCode == areaCode);
// second:
var query = _context.myTable
.Select(s => new TestDto(s.CellLocationId, s.AreaCode));
query = query.Where(x => x.AreaCode == areaCode);
These pieces of code, if there is really nothing else between context:get_myTable and IQueryable<record>:Where, something that you'd for some reason omit, then these two pieces of code are essentially the same. Or should be.
When we write return " mom ".ToUpper().Trim(); we don't expect it to have different results than if we write var x = " mom ".ToUpper(); x = x.Trim(); return x;, right? That's all complete basics of operation/result/variable semantics.
The only difference here is splitting such unmaterialized IQueryable 'result' of a .Select() to a variable. LINQ call chain is exactly the same. Names are exactly the same. Difference is purely syntactical. So if you see that one of them works, and the other fails, this means there's a bug in the compiler, and you should:
file a bug issue at roslyn github
get away from whatever this bug can be related to as far as possible (meaning not use records yet, or at least not early in the query)
or, at least test the hell out of it, so you know how to use it safely even bugged, and get as much of those tests automated
There's really not much else to be advised here.
(1) actually sometimes it is problematic. Every ".Select" in the chain changes the "shape of the query", as they call it sometimes in MSDN articles, and it usually breaks any .Include setups that were done on the original shape. But YMMV there.
(2) anon-types are perfect here from the LINQ point of view, but are often a nightmare for the developer who wants to do anything a bit more reusable or structured. You cannot return them easily from your methods, since the type is anonymous. And so on. This severely limits reuse, and I can easily imagine, that's why RecordTypes are introduced - to provide a plain type with guaranteed mechanics, a type that can be named and easily referred to.
what is the problem with the following code?
var results = db.Departments.Select(x => customfunction(x.DepartmentID));
results.toList();
Why this is this not caught in compile time but gives an exception in runtime?
There are many different LINQ providers that allow you to use LINQ against a variety of data sources (LINQ to Entities, LINQ to Objects, LINQ to XML among others).
Although LINQ to Entities does not know how to invoke your custom method (at least, not the providers for common databases), some LINQ providers might well understand how to execute myfunction. The compiler is not integrated with all of the many LINQ providers, so the information as to whether your custom method can be included is only available at runtime.
In fact, LINQ to Objects can execute it
var results = db.Departments
.AsEnumerable()
.Select(x => myfunction(x.DepartmentID));
The conversion of
db.Departments.Select(x => myfunction(x.DepartmentID));
to sql does not happen until very late in the process at runtime.
So at compilation time Entity Framework does not know that myFunction is not something it is not going to know how to convert to sql yet.
of course you could do
db.Departments.Select(x => (x * 2));
And EF will happily be able to translate to sql but if you try to use a custom property on Departments object that doesn't map to a field in the db or use a custom method that that the Linq data provider does not know how to translate to sql you will get the same error.
The idea is simple: .Select(x => myfunction(x.DepartmentID)) is never executed in C#. Instead, Entity Framework parses this expression and translates it to SQL.
For example, if you call .Count() in C# EF will translate this to SELECT COUNT(...)
This is all very powerful, except for a few cases such as yours.
EF analyzes your code through Expression Trees.
If you call myFunction() in an expression tree, it is impossible to "expand" that call to get the body of your function. This is a limitation of how C# is implemented. That's why EF is unable to generate sensible SQL, because it has no clue what your method does.
However, there is a reasonable alternative: LinqKit
LinqKit will allow you to write "functions" that are reusable in your expressions.
Example:
static string[] QueryCustomers (Expression<Func<Purchase, bool>> purchaseCriteria)
{
var data = new MyDataContext();
var query = from c in data.Customers.AsExpandable()
where c.Purchases.Any (purchaseCriteria.Compile())
select c.Name;
return query.ToArray();
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I am really confused to understand its internal working
This is LINQ syntax
string[] test = new test[] { "abc", "", "cd", "", "aa" };
test = test.Where(x => !string.IsNullOrEmpty(x)).ToArray();
I am confused about where syntax how it manages. is it put all array in x? if yes then how it manage x null value?
or
if not then test array values put one by one in the x?
You should consider the rest of the answers, they are pretty accurate, what I want to show you and maybe this will help you to understand the syntax is that this kind of query can actually be represented in a query syntax like this:
string[] test=new test[]{"abc","","cd","","aa"};
// this is the equivalent to your code
// added explicit type to make it clearer, it's optional
var a = from (string)x in test
where !string.IsNullOrEmpty(x)
select x;
if you are familiar with SQL, you will find this syntax easier to read, even when you do not know it, this syntax is cleaner.
When the code is compiled, this query syntax is automatically translated to the C# method syntax, in order to generate the IL, so if you dissasmbly a DLL you will see the method syntax instead of the query syntax
A brief explanation about this code:
As you can see an x variable was declared and it's of type string. Why? because your array is an array of strings
The in test indicates the source IEnumerable<> to iterate - your array in this case
The where is pretty explanatory, it simply selects all not null strings from your array
And finally the selects which actually is a projection of the data.
And all this is equivalent to your code
Now you might be asking yourself... When should I use one syntax or the other? Well they are equivalent but the query syntax operators are limited which means that most of the operations are done with method syntax instead of query syntax. What I always do is try to write the code easier to read some code is easier to understand if it is written with a query syntax.
About the method syntax, the x => ... syntax is known as lambda expression, they might look weird if it is the first time you are working with them but you will love them eventually.
Basically lambdas are shortcuts to delegates, so what you are doing with:
x => !string.IsNullOrEmpty(x)
You are creating an anonymous method and the method is being assigned to the delegate parameter. The x represents the string variable.
This topic is really extensive to try to explain it here, but I hope this has given you an idea of what's behind.
Btw you can combine the syntax's like this:
// this is the equivalent to your code
// added explicit type to make it clearer, it's optional
var a = (from (string)x in test
where !string.IsNullOrEmpty(x)
select x).ToArray();
If you google LINQ is like googling porm lol the web is plagued with LINQ articles, samples, etc.
A good point of start would be the 101 samples from Microsoft
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
EDIT
I will try to emulate the Where method so you can have a better example of the lambda expression
// this is basically the declaration of one overload of the Where method
// the this in the parameter declaration, indicates this is an extension method which will be available to all IEnumerable<> objects
// the Func<T, bool> is the interesting part, it is basically a delegate (as a reminder, the last parameter of the Func object indicates the type that must be returned, in this case is a bool)
// the delegate is simply a pointer to a function
public IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
...some logic
... yielding back the reuslts
foreach(var r in res)
{
// here is the delegate in action
if(predicate(r))
yield return r;
}
}
As you can see the delegate was called as a function (delegates are pointer to functions)
Butt what function??? the one you declared in your code
x => !string.IsNullOrEmpty(x) and the x indicates the parameter passed back from the Where method to the external code, where you can inspect it and use it to filter your results
The x => is an abbreviation to declare a delegate
!string.IsNullOrEmpty(x) this is the body of your anonymous method and as you can see it fulfills the requirements of the Func<T, bool> it is returning a bool (the predicate to filter the elements of the array) and as a parameter, it received the generic T which in this case is a string from your array
Another way to declare the lambda expression is:
test = test.Where(
(string) x =>
{
return !string.IsNullOrEmpty(x)
})
.ToArray();
With this syntax is easy to show that they are actually methods (anonymous methods)
we can take the statement apart and examine the pieces one at a time
x => !string.IsNullOrEmpty(x) is basically defining a function like the below
bool Filter(string x){
return !string.IsNullOrEmpty(x)
}
and creates a Predicate based on that function. A predicate is just a delegate - a function you can pass in a variable.
.Where is an extension method that for simplicity could be defined
IEnumerable<T> Where<T>(this IEnumerable<T> sequence,Predicate<T> pred){
foreach(var elem in sequence){
if(pred(elem)){
yield return elem;
}
}
}
had you defined the function as Filter is defined above instead of using a lambda your statement would look like this
test = test.Where(Filter).ToArray();
so by calling this extension method on your array and passing the above predicate you will iterate over all elements in the array and return all those elements that matches the predicate (Ie. those that are neither null nor have the value of the empty string)
Finally you call the extension method .ToArray() which turns what .Where returned (an IEnumerable<string>) into an array
EDIT
Read this article you will surely get good idea about that you have writtnen......
C# 3.0 New Language Features (Part 1)
C# 3.0 New Language Features (Part 2)
it's from of extenstion method + lambda experssion part of C# 3.0
here in this code
test=test.Where(x => !string.IsNullOrEmpty(x)).ToArray();
where - is a extesion method
x => !string.IsNullOrEmpty(x) - is lambda expresion , which is replacement of anonymous function
this whole function check the each element of array ...i.e the lamdaba expression check the each element of the array satisfy the conditon which is written and than finally retuns array of those element which satisfy the condition
Below are two queries that return the same data. Other then style I am not sure which is better.
What factors influence these queries?
What are the benefits of using one style over the other?
Sample 1
var x = from s in db.Surveys
join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
join q in db.Questions on sq.Question_ID equals q.ID
join qg in db.Question_Groups on q.ID equals qg.Question_ID
where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
select new { question = sq.Question, status = sq.Status, grp = qg };
Sample 2
var x = db.Surveys.Where(s => s.Type_ID.Equals(typeID) & s.Type.Equals(type))
.Join(db.Survey_Questions,
s => s.ID,
sq => sq.Survey_ID,
(s, sq) => new
{
question = sq.Question,
status = sq.Status
})
.Join(db.Question_Groups,
q => q.question.ID,
qg => qg.Question_ID,
(q, qg) => new
{
question = q.question,
status = q.status,
group = qg
}).ToList();
Update: You have fixed your title, so ignore the rant.
The title of your question has nothing to do with your code samples. Your question implies that one syntax is IEnumerable and the other is IQueryable, but this is incorrect. In your samples, if db.Surveys is an IQueryable, then both your samples are using IQueryable. I will try to answer both questions.
Your two code samples are just different ways of writing the same LINQ queries (assuming they are well-written). The code in sample 1 is just shorthand for the code in sample 2. The compiler treats the code in both samples the same way. Think of the way the C# compiler will treat int? the same as Nullable<System.Int32>. Both the C# and VB.Net languages provide this shorthand query syntax. Other languages might not have this syntax and you would have to use the sample 2 syntax. In fact, other languages might not even support extension methods or lambda expressions, and you would have to use an uglier syntax yet.
Update:
To take Sander's example further, when you write this (query comprehension syntax):
var surveyNames = from s in db.Surveys select s.Name
You think the compiler turns that shorthand into this (extension methods and lambda expression):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
But actually extension methods and lambda expressions are shorthand themselves. The compilers emits something like this (not exactly, but just to give an idea):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
Note that Select() is just a static method in the Queryable class. If your .NET language did not support query syntax, lambdas, or extension methods, that is kinda how you would have to write the code yourself.
What are the benefits of using one style over the other?
For small queries, extension methods can be more compact:
var items = source.Where(s => s > 5);
Also, the extension method syntax can be more flexible, such as conditional where clauses:
var items = source.Where(s => s > 5);
if(smallerThanThen)
items = items.Where(s => s < 10);
if(even)
items = items.Where(s => (s % 2) == 0);
return items.OrderBy(s => s);
In addition, several methods are only available through extension method syntax (Count(), Aggregate(), Take(), Skip(), ToList(), ToArray(), etc), so if I'll use one of these, I'll usually write the whole query in this syntax to avoid mixing both syntaxes.
var floridaCount = source.Count(s => s.State == "FL");
var items = source
.Where(s => s > 5)
.Skip(5)
.Take(3)
.ToList();
On the other hand, when a query gets bigger and more complex, query comprehension syntax can be clearer, especially once you start complicating with a few let, group, join, etc.
In the end I will usually use whichever works better for each specific query.
Update: you fixed your title, so ignore the rest...
Now, about your title: With respect to LINQ, IEnumerable and IQueryable are very similar. They both have pretty much the same extension methods (Select, Where, Count, etc), with the main (only?) difference being that IEnumerable takes Func<TIn,TOut> as paremeters and IQueryable takes Expression<Func<TIn,TOut>> as parameters. You express both the same way (usually lamba expressions), but internally they are completely different.
IEnumerable is the doorway to LINQ to Objects. The LINQ to Objects extension methods can be called on any IEnumerable (arrays, lists, anything you can iterate with foreach) and the Func<TIn,TOut> is converted to IL at compile time and runs like a normal method code at run time. Note that some other LINQ providers use IEnumerable and so are actually using LINQ to Objects behind the scenes (LINQ to XML, LINQ to DataSet).
IQueryable is used by LINQ to SQL, LINQ to Entities, and other LINQ providers which need to examine your query and translate it instead of executing your code directly. IQueryable queries and their Expression<Func<TIn,TOut>>s are not compiled into IL at compile time. Instead an expression tree is created and can be examined at run time. This allows the statements to be translated into other query languages (for example T-SQL). An expression tree can be compiled into a Func<TIn,TOut> at run time and executed if desired.
An example that illustrates the difference can be found in this question where the OP wants to do part of a LINQ to SQL query in SQL Server, bring the objects into managed code, and do the rest of the query in LINQ to Objects. To achieve this all he has to do is cast the IQueryable into an IEnumerable where he wants the switch to happen.
LINQ is buzz word for a technology.
IQueryable is a .NET Interface which is used by LINQ.
Other than the style, there is no difference between the two. Use whichever style you prefer.
I prefer the first style for long statement (like that one shown here) and the second for very short statements.
The where clause in the first example is actually just syntactic sugar for the Where clause in your second method. In fact, you can write your own class that has nothing to do with Linq or IQueryable and just by having a Where method, you can use that syntactic sugar. For example:
public class MyClass
{
public MyClass Where<T>(Func<MyClass, T> predicate)
{
return new MyClass { StringProp = "Hello World" };
}
public MyClass Select<T>(Func<MyClass, T> predicate)
{
return new MyClass ();
}
public string StringProp { get; set; }
}
This is obviously a stupid example, but note that there's a Where method that just returns a new MyClass with stringprop set to Hello World. To demonstrate:
MyClass a = new MyClass();
var q = from p in a
where p.StringProp == "foo" // doesnt matter what we put here, as we're not really checking the predicate
select p;
Console.WriteLine(q.StringProp);
This will result in writing out "Hello World". Again, this example is obviously pointless, but it proves the point that the "where" syntax just looks for a Where method in your code that takes a Func.
Query expressions and extension methods are two ways to do the exact same thing. Query expressions get transformed to extension methods when compiling - they are just syntactic sugar for people who are more comfortable with SQL.
When you write this:
var surveyNames = from s in db.Surveys select s.Name;
The compiler transforms this into:
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
Really, I think query expressions were just created for marketing reasons - a SQL-like language construct to act as an eye-catcher when LINQ was developed, not something that offers much actual use. I find that most people just use the extension methods directly, as they result in a more unified coding style, instead of a mix of C# and SQL.
1./ Your question title does not match what you asked.
2./ Your question title does not really make sense. Linq stands for Language Integrated Query and is an umbrella term for a bunch of technologies and practices, IQueryable is an interface that is commonly used to facilitate Linq. you are comparing Apples and Oranges
3./ About your actual question, the main difference is style, for complex queries like this one, my personal preference is the 2nd version, as it clearly shows the progression of the result sets.
Your Sample1 is top level representation of Linq, it is more readable, and while compiling it'll converted to expression tree i.e your Sample2.
var x = from s in db.Surveys
join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
join q in db.Questions on sq.Question_ID equals q.ID
join qg in db.Question_Groups on q.ID equals qg.Question_ID
where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
select new { question = sq.Question, status = sq.Status, grp = qg };
you can try below code to get expression for written query
var exp=x.Expression;
Expressions are used when query less complicated
I think your question is better phrased like this, "What is the difference between IEnumerable<T> and IQueryable<T> with respect to LINQ"
LINQ queries return an IQueryable<T> by default. IQueryable<T> allows you to append other filters or "clauses" onto your query before you execute it.
Your LINQ query (first example) and your LINQ using method chaining (second example) produce the same result, with different syntax.
It is possible to write a LINQ query as a LINQ method chain and visa versa. It really depends on your preference.
#Lucas: The different is IEnumerable<T> does in-memory querying and IQueryable<T> does out-of-memory. Meaning, once you are in a foreach iterator, you are using IEnumerable, and when you are building your query, via either extension methods or using LINQ from o in object synatax, you are building an IQueryable<T>. The IQueryable<T> is executed as soon as you touch the Enumerator.
Another point worth mentioning is that the Linq extension methods adhere to C# language whereas the query comprehension stuff is preprocessed like is built into the compiler.
i.e you can navigate to the definition of .Select(x =>
whereas you cannot for from ... where ... select
I'm trying to get a handle on if there's a good time to use standard linq keywords or linq extension methods with lambda expressions. They seems to do the same thing, just are written differently. Is it purely a matter of style?
var query = from p in Products
where p.Name.Contains("foo")
orderby c.Name
select p;
// or with extension methods:
var query = Products
.Where(p => p.Name.Contains("foo"))
.OrderBy(p => p.Name);
They're very similar with the second example being a bit more terse, but perhaps less expressive if you don't know what the => is doing.
Other than writing terse code, are there other advantages to using the extension methods as opposed to the LINQ syntax?
Honestly, sometimes it can be situational once you start using Funcs and Actions. Say you are using these three funcs:
Func<DataClasses.User, String> userName = user => user.UserName;
Func<DataClasses.User, Boolean> userIDOverTen = user => user.UserID < 10;
Func<DataClasses.User, Boolean> userIDUnderTen = user => user.UserID > 10;
As you can see the first one replaces the lamdba expression to get the user name, the second replaces a lamdba expression used to check if the ID is lower than 10, and let's face it, the third should be pretty easy to understand now.
NOTE: This is a silly example but it works.
var userList =
from user in userList
where userIDOverTen(user)
select userName;
Versus
var otherList =
userList
.Where(IDIsBelowNumber)
.Select(userName)
In this example, the second is a little less verbose since the extension method can make full use of the Func, but he Linq expression can't since it is look just for a Boolean rather than a Func that returns boolean. However, this is where it might be better to use the expression language. Say you already had a method that takes in more than just a user:
private Boolean IDIsBelowNumber(DataClasses.User user,
Int32 someNumber, Boolean doSomething)
{
return user.UserID < someNumber;
}
Note: doSomething is just there because of the where extension method being ok with a method that takes in a user and integer and returns boolean. Kind of annoying for this example.
Now if you look at the Linq query:
var completeList =
from user in userList
where IDIsBelowNumber(user, 10, true)
select userName;
You're good for it. Now the Extension Method:
var otherList =
userList
.Where(IDIsBelowNumber????)
.Select(userName)
Without a lambda expression, I really can't call that method. So now what I have to do is create a method that creates a Func based off the original method call.
private Func<DataClasses.User, Boolean> IDIsBelowNumberFunc(Int32 number)
{
return user => IDIsBelowNumber(user, number, true);
}
And then plug it in:
var otherList =
userList
.Where(IDIsBelowNumberFunc(10))
.Select(userName)
So you can see, sometimes it may just be easier to use the query approach at times.
One advantage to using LINQ extension methods (method-based queries) is that you can define custom extension methods and it will still read fine.
On the other hand, when using a LINQ query expression, the custom extension method is not in the keywords list. It will look a bit strange mixed with the other keywords.
Example
I am using a custom extension method called Into which just takes a string:
Example with query
var query = (from p in Products
where p.Name.Contains("foo")
orderby c.Name
select p).Into("MyTable");
Example with extension methods
var query = Products
.Where(p => p.Name.Contains("foo"))
.OrderBy(p => p.Name)
.Into("MyTable");
In my opinion the latter, using a method-based query, reads better when you have custom extension methods.
I think it's a good idea not to use them together and choose one and stick with it.
Mostly it's personal taste, but in the query syntax (Comprehension method) not all operators are available as was said before.
I find the Extension Methods syntax more in line with the rest of my code. I do my SQL in SQL. It's also very easy to build your expression just by adding everything on top of eachother with the extension methods.
Just my two cents.
As I cannot make comments yet I want to make one here to the answer of Programming Tool:
Why make a whole new method for the last example?? Can't you just use:
.Where(user => IDIsBelowNumber(user, 10, true))
They compile the same, and are equivalent. Personally, I prefer the lambda (extension) methods for most things, only using the statements (standard) if I'm doing LINQ to SQL or otherwise trying to emulate SQL. I find that the lambda methods flow better with code, whereas the statements are visually distracting.
I prefer the extension method syntax when I use Linq methods that have no query syntax equivalent, such as FirstOrDefault() or others like that.
I like to use the query syntax when its really a query, ie a lazy expression which evaluates on demand.
A method that looks like regular method calls (method syntax or the lambda syntax) doesn't look lazy enough, so I use that as a convention. For eg,
var query = from p in Products
where p.Name.Contains("foo")
orderby p.Name
select p;
var result = query.ToList(); //extension method syntax
If it's a not a query, I like the fluent style which looks to me consistent with other eagerly executing calls.
var nonQuery = Products.Where(p => p.Name.Contains("foo"))
.OrderBy(p => p.Name)
.ToList();
It helps me to differentiate the two styles of calls better. Of course there are situations where you will be forced to use method syntax anyway, so my convention is not very compelling enough.
One advantage of extension methods/lynda expressions is the additional operators that is offered like Skip and Take. For example, if you are creating a pagination method, being able to skip the first 10 records and take the next 10 is easy to implement.