I find LINQ a little difficult to wrap my head around. I like the concept and believe it has lots of potential. But, after writing so much SQL the syntax is just not easy for me to swallow.
A. What is the deal with multiple ways to select?
I see that I am able to create a context and perform a Select() using a method.
context.Table.Select(lamba expression);
ok...Why would I use this? How does it compare to (or does it) this type of select?
var returnVal = from o in context.Table
orderby o.Column
select o;
B. Please explain the variable nature of
**from X** in context.Table
Why do we stick a seemingly arbitrarily named variable here? Shouldn't this be a known type of type <Table>?
So...
var returnVal = context.Table.Select(o => o);
and
var returnVal = from o in context.Table
select o;
are the same. In the second case, C# just has nice syntactic sugar to give you something closer to normal SQL syntax. Notice I removed the orderby from your second query. If you wanted that in there, then the first one would become:
var returnVal = context.Table.OrderBy(o => o.Column).Select(o => o);
As for your last question... we're not sticking an arbitrarily named variable here. We're giving a name to each row so that we can reference it later on in the statement. It is implicitly typed because the system knows what type Table contains.
In response to your comment, I wanted to add one more thought. You mentioned things getting nasty with the normal method calls. It really can. Here's a simple example where its immediately much cleaner (at least, if you're used to SQL syntax) in the LINQ syntax:
var returnVal = context.Table.OrderBy(o => o.Column1)
.ThenBy(o => o.Column2)
.ThenBy(o => o.Column3)
.Select(o => o);
versus
var returnVal = from o in context.Table
orderby o.Column1, o.Column2, o.Column3
select o;
A: this is the same. The compiler transforms the query expression to method calls. Exactly the same.
B: The x is the same as in foreach(var X in context.Table). You define a name for an individual element of the table/sequence.
In B, X's type is implicit. You could just as easily do something like:
from Row x in context.Table
and it would be the same. In A, there isn't any difference between using a lambda and the equivalent full-LINQ syntax, except that you would never do .Select(x => x). It's for transforming items. Say you had a list of integers, .Select(x => x * x) would return the square of each of them.
Related
Can this be turned into a select statement?
foreach (var gf in CreateGenericFieldsOnInspection(model))
{
simpleInspection.GenericFields.Add(gf.GenericFieldDefinition.Name,
new LC360Carrier.Domain.Models.Import.GenericField
{
GenericFieldType = GenericFieldValueType.Text,
Value = gf.Value
});
}
It looks like GenericFields is a Dictionary<string, GenericFieldOrSomething>. You could contort this into something really weird for the sake of using LINQ. But the purpose of LINQ is to query one or more IEnumerables to either get a result or transform them into something else.
It's just like SQL. You query it to either get a set of records or some value like the sum of some numbers.
In your case you've already got a result set - whatever CreateGenericFieldsOnInspection(model) returns. It makes sense to do what you're already doing - foreach through the results and perform some action on each one of them.
LINQ would be handy if you needed to query that set. For example,
var filteredProperties = CreateGenericFieldsOnInspection(model)
.Where(property => property.Name.StartsWith("X"));
But even then, once you had that collection, it would still make sense to use a foreach loop.
You'll see this sometimes - I did it when I first learned LINQ:
CreateGenericFieldsOnInspection(model).ToList()
.ForEach(property => DoSomethingWith(property));
We convert something to a List because then we can use .ForEach. But there's no benefit to it. It's just foreach with different syntax and an extra step.
I have an extension method that permits add. I was just having trouble w the syntax. Bagus Tesa, above was also helpful. Thanks.
simpleInspection.GenericFields = simpleInspection.GenericFields.Union(CreateGenericFieldsOnInspection(model).Select(x => new KeyValuePair<string, object>(x.GenericFieldDefinition.Name, new LC360Carrier.Domain.Models.Import.GenericField
{
GenericFieldType = GenericFieldValueType.Text,
Value = x.Value
}))).ToDictionary(x => x.Key, x => x.Value);
It's amazing how little information there is on this. I found tons of tutorials explaining LINQ, but they don't explain this particular operator:
var Results = UserFavoritesContext.UserFavorites.Select(color => color.FavoriteColor);
"x => x.y"
Can someone please explain how this works? I get the general syntax and am able to use it to make queries, but it's like doing something without knowing what you're doing.
Suppose you have a list of people, and you want to iterate over them. You would write something like:
foreach(var person in people)
{
//do something to person
}
Note how you yourself chose the name person. It could've been any word, but you basically said "process every single item of the list as my person variable".
Now look at this LINQ query:
filteredPeopleList = people.Where(person => person.Name == "John");
Again, you basically chose person as a placeholder name for every object in the original list (one at a time). The above Linq query is equivalent to
foreach(var person in people)
{
if(person.Name == "John")
{
filteredPeopleList.Add(person);
}
}
To me, x => x.y is basically saying "for every variable we process (let's call it x), please perform the following operation on it (x.y, get the y property)"
I hope that explains it.
Edit
As a commenter who now deleted his comment mentioned, this isn't exclusively used in LINQ. A lambda expression doesn't have to iterate over an IEnumerable, it can be used to process a single item.
However, LINQ is by far the most common place to encounter lambdas, and I find their use very similar to the foreach loop, which is why I picked this example.
The => operator is used in lambda expressions.
The best way to think of this is a type of syntax for writing a function, where the left side of the operator is the parameters for the function and the right side is the body of the function e.g. this is a valid use of a lambda expression where its being used like a function:
Func<int, int> incrementFunction = i => i + 1;
int incrementedNumber = incrementFunction(1);
The name i in this case is an arbitrary variable name e.g. just like you would name a functions input parameter. Notice I didnt need to declare the input parameters type because the compiler will infer it. Also notice I dont need to include the "return" keyword or enclose the function body in a code block. It doesn't necessarily need any parameters either e.g.
Action myAction = () => Console.Write("something");
myAction();
When you use it in a linq expression, think of it as though the lambda function is being called on every element in the collection (which I believe is exactly what happens with linq to objects).
It's the syntax of a Lambda expression. If it helps you to remember... in a nutshell, the argument to pass (the parameter) is on the left of the => and the method(s) that use it are on the right hand side of it.
I hope this short summary explains it enough :)
That is a lambda expression, and it can be used as a selector from an object
You can conditionally select (or another operation orderby, count, etc) when the expression is true. For example:
Say you had a list of people and their details: ID, Name, City and Profession.
You could select a single person by using lambda to search for their specific ID:
public Person GetByID(int id)
{
Person selectedPerson = people.SingleOrDefault(person => person.ID == id);
return selectedPerson;
}
Same could be applied for a select on a city, this would be:
public List<Person> GetByCity(string city)
{
List<Person> selectedPeople = people.where(person => person.City == city);
return selectedPeople;
}
The lamda expression is where you place your operation variable, so in these cases the condition upon which you select the data. You can use it as a orderby variable much in the same way, in the next example I use two lamdas to perform two seperate functions
public List<Person> GetByCity(string city)
{
List<Person> selectedPeople = people.where(person => person.city == city)
.OrderByDescending(person => person.Name);
return selectedpeople;
}
I hope this helps at all
x => x.y is Lambda Expression introduced with C# 3.0. The general syntax is
parameter => executioncode
The Lambda Expression has 3 parts:
x on left hand side is the parameter.This can be a variable,delegate or an anonymous function.
=> read as "goes to", which acts as separator
x.y is an Expression to be evaluated.
For example, the lambda expression x => x * x specifies a parameter that’s named x and returns the value of x squared (source: MSDN).
Hope this would help you.
They're called Lamda expression:
https://msdn.microsoft.com/en-us/library/bb397687.aspx
var Results = UserFavoritesContext.UserFavorites.Select(color => color.FavoriteColor);
is similar to:
List<UserFavorite> Results = new List<UserFavorite>();
foreach(var item in UserFavorites)
{
Results.Add(item.FavoriteColor);
}
This is not specific to Linq.
It is the way you write a lambda expression.
The arrow => is the delimiter between your lambda parameters and its body.
My simplified LINQ Join plus Where of two tables looks like this:
var join = context.Foo
.Join(context.Bar,
foo => new { foo.Year, foo.Month },
bar => new { bar.Year, bar.Month },
(foo, bar) => new { foo.Name, bar.Owner, foo.Year })
.Where(anon => anon.Year == 2015).ToList();
Alternatively I could have used the following syntax that I hope to be equivalent:
var joinQuery = from foo in context.Foo
join bar in context.Bar
on new { foo.Year, foo.Month } equals new { bar.Year, bar.Month }
where foo.Year == 2015
select new { foo.Name, bar.Owner };
var join = joinQuery.ToList();
One difference that occurs to me and that I wonder about is the order of commands. In the lambda-syntax join I add the foo.Year property to my anonymous return type just so I can filter after, while in the other query I can still use foo (and bar if I wanted to) in the where clause. I don't need to add the field foo.Year to my return type here if I don't want or need to.
Unfortunately I don't have ReSharper or anything similar that could translate the lower statement to a lambda one so that I could compare.
What I could in fact do (and make the upper statement more similar in structure to the lower one) is add the following line between Where(..) and ToList() in the first one:
.Select(anon => new { /* the properties I want */ })
But doesn't this just add "one more" anonymous type creation compared to the 2nd statement, or am I mistaken here?
In short: What's the equivalent Join syntax to the 2nd statement? Or is the 1st one plus the added Select really equivalent, that is, does the joinQuery internally produce the same code?
In the general case, you cannot always convert between query comprehension syntax and lambda syntax in exactly the same way the compiler does. This is due to the usage of transparent identifiers. But you can work around this and produce semantically equivalent lambda statements. And this is what ReSharper does.
Anyway, in your case, you can just add:
.Select(anon => new { /* the properties I want */ })
This will instantiate an anonymous type per row, but it won't be "one more", so don't worry about that: the expression is converted to SQL, so the new { foo.Year, foo.Month } statements in the join don't really instantiate these objects, they just get converted to SQL. Only the last select will both be used for the SQL SELECT list, and for object hydration once the rows are retrieved.
But doesn't this just add "one more" anonymous type creation compared to the 2nd statement, or am I mistaken here?
As dotctor's answer shows: this is what the compiler is doing when you use the comprehension syntax in this case. By including the year in your single anonymous type you slightly reduce the overhead.
However:
Anonymous types are very lightweight: the use of generics, and that generics instantiated over reference types share implementation means there is little code (take a look at the assembly in a decompiler).
While lots of instances are created, for most cases they'll be cleaned up in generation 0 as they are released almost immediately.
The C# compiler's and JIT's optimisers have plenty to work with here. It is quite possible shortcuts are taken (but you'll need to read the x86/x64 assembly from a running process to see).
Remember the first two rules of optimisation: unless you can show – profiler data from realistic test data – you have a performance issue focus on clear code that is easy to maintain.
Another alternative would be to move the where method before the join method and then leave the year out of the anonymous class:
var join = context.Foo
.Where(foo => foo.Year == 2015)
.Join(context.Bar,
foo => new { foo.Year, foo.Month },
bar => new { bar.Year, bar.Month },
(foo, bar) => new { foo.Name, bar.Owner })
.ToList();
But in general the other answers are right in that there is not much difference and the compiler can handle the details for you .
for the In short: part of your question: the answer is yes.
here is resharpers result
var joinQuery = context.Foo.Join(context.Bar, foo => new
{
foo.Year,
foo.Month
}, bar => new
{
bar.Year,
bar.Month
}, (foo, bar) => new
{
foo,
bar
}).Where(#t => #t.foo.Year == 2015).Select(#t => new
{
#t.foo.Name,
#t.bar.Owner
});
In EF, when you want to include a navigation property in the result of a query, you use Include(). Since some queries require calling this more than once, I tried to create a generic wrapper around this concept:
public IQueryable<T> FindAll<P>(params Expression<Func<T, P>>[] predicates) where P : class {
var entities = AllEntities();
foreach (var p in predicates) entities = entities.Include(p);
return entities;
}
And call it as such:
var customers = FindAll(q => q.Orders, q => q.Invoices, q => q.Contacts);
Questions:
The function compiles, but when I call it: "The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly." What am I doing wrong?
If I get it to work, can I call Include() the first time: var customers = FindAll(q => q.Orders, q => q.Invoices); and then again later in a separate step: customers = customers.Include(p => p.Invoices); or will that result in poor performance such that I should do the includes in one go?
EDIT:
JonSkeet's answer is correct, of course, and yet there is this solution which seems to do what I want. Not sure why it works however. Is it because of the Aggregate() function?
Fundamentally, I think you've got a problem - assuming that q.Orders, q.Invoices and q.Contacts return different types, you can't express what you want to happen. You probably want something like:
entities.Include<Parent, Order>(p => p.Order);
entities.Include<Parent, Invoice>(p => p.Invoices);
entities.Include<Parent, Contact>(p => p.Contacts);
... so you want a different value for P for each predicate. But you're calling a single method, providing a single type argument for P.
It's not clear that this is really giving you much benefit anyway... couldn't you just write:
var customers = AllEntities().Include(q => q.Orders)
.Include(q => q.Invoices)
.Include(q => q.Contacts);
I'd say that's clearer and it gets round the "multiple type parameters" problem.
a) Would the following two queries produce the same results:
var query1 = collection_1
.SelectMany(c_1 => c_1.collection_2)
.SelectMany(c_2 => c_2.collection_3)
.Select(c_3 => c_3);
var query2 = collection_1
.SelectMany(c_1 => c_1.collection_2
.SelectMany(c_2 => c_2.collection_3.Select(c_3 => c_3)));
b) I assume the two queries can't always be used interchangeably? For example, if we wanted the output elements to also contain values of c_1 and c_2, then we only achieve this with query2, but not with query1:
var query2 = collection_1
.SelectMany(c_1 => c_1.collection_2
.SelectMany(c_2 => c_2.collection_3.Select(c_3 => new { c_1, c_2, c_3 } )));
?
Thank you
The snippets you've given seem to be invalid. c_3 isn't defined in the scope of the Select statement, so unless I've misunderstood something, this won't compile.
It seems as though you're trying to select the elements of collection_3, but this is done implicitly by SelectMany, and so the final Select statements in both cases are redundant. Take them out, and the two queries are equivalent.
All you need is this:
var query = collection_1
.SelectMany(c_1 => c_1.collection_2)
.SelectMany(c_2 => c_2.collection_3);
Update: x => x is the identity mapping, so Select(x => x) is always redundant, regardless of the context. It just means "for every element in the sequence, select the element".
The second snippet is of course different, and the SelectMany and Select statements indeed need to be nested in order to select all three elements, c_1, c_2, and c_3.
Like Gert, says, though, you're probably better off using query comprehension syntax. It's much more succinct and makes it easier to mentally parse the workings of a query.
a. The queries are equal because in both cases you end up with all c_3's in c_1 through c_2.
b. You can't get to c_1 and c_2 with these queries as you suggest. If you want that you need this overload of SelectMany. This "fluent" syntax is quite clumsy though. This is typically a case where comprehensive syntax which does the same is much better:
from c_1 in colection_1
from c_2 in c_1.collection_2
from c_3 in c_2.collection_3
select new { c_1.x, c_2.y, c_3.z }