I see this all over the web, however I'm curious if there isn't an easier way to write this in lambda?
var x = from c in db.Client
from p in db.Prospects
from ct in db.Countys
select new ViewModelExcelReport
{
client = c.ClientName,
cntyCounty = ct.County,
sctSection = p.Section
};
I would like to see a lambda expression that does NOT use joins, as though i am almost certain that i have seen one without the joins, but if this isn't possible ofcouse i'd like to see one with, thanks.
Basically multiple from clauses contribute SelectMany calls. So your code is something like:
var x = db.Client
.SelectMany(c => db.Prospects, (c, p) => new { c, p })
.SelectMany(z => db.Countys, (z, ct) => new { z, ct })
.Select(zz => new ViewModelExcelReport
{
client = zz.z.c.ClientName,
cntyCounty = zz.ct.County,
sctSection = zz.z.p.Section
});
Note how this is rather more longwinded than the query expression - the compiler takes care of keeping track of all the range variables via transparent identifiers. Why do you want this in lambda form? What do you see as being the benefit? The query expression will be translated into exactly the same code, so you should use whichever one is clearer - which in this case looks like the query expression, IMO.
As an aside, I'd strongly recommend that you change your property names (in ViewModelExcelReport) to more idiomatic ones if you possibly can.
Related
var sample = db.Database.OrderByDescending(x => x.RecordId).Select(y => y.RecordId).FirstOrDefault();
I don't know if my title is correct / right. Just want to ask why this query the select is in another ( )?. As for the example .Select(y => y.RecordId) unlike the query I use to be
var sample = (from s in db.Databse where s.RecordId == id select s) I know this is the same right?. Then what is the why it is in another parenthesis?. Anyone has an idea or can anyone explain it why?. Thanks a lot.
In your first example, you're using "regular" C# syntax to call a bunch of extension methods:
var sample = db.Database
.OrderByDescending(x => x.RecordId)
.Select(y => y.RecordId)
.FirstOrDefault();
(They happen to be extension methods here, but of course they don't have to be...)
You use lambda expressions to express how you want the ordering and projection to be performed, and the compiler converts those into expression trees (assuming this is EF or similar; it would be delegates for LINQ to Objects).
The second example is a query expression, although it doesn't actually match your first example. A query expression corresponding to your original query would be:
var sample = (from x in db.Database
orderby x.RecordId descending
select x.RecordId)
.FirstOrDefault();
Query expressions are very much syntactic sugar. The compiler effectively converts them into the first form, then compiles that. The range variable declared in the from clause (x in this case) is used as the parameter name for the lambda expression, so select x.RecordId becomes .Select(x => x.RecordId).
Things become a bit more complicated with joins and multiple from clauses, as then the compiler introduces transparent identifiers to allow you to work with all the range variables that are in scope, even though you've really only got a single parameter. For example, if you had:
var query = from person in people
from job in person.Jobs
order by person.Name
select new { Person = person, Job = job };
that would be translated into the equivalent of
var query = people.SelectMany(person => person.Jobs, (person, job) => new { person, job } )
.OrderBy(t => t.person.Name)
.Select(t => new { Person = t.person, Job = t.job });
Note how the compiler introduces an anonymous type to combine the person and job range variables into a single object, which is used later on.
Basically, query expression syntax makes LINQ easier to work with - but it's just a translation into other C# code, and is neatly wrapped up in a single section of the C# specification. (Section 7.16.2 of the C# 5 spec.)
See my Edulinq blog post on query expressions for more detail on the precise translation from query expressions to "regular" C#.
I have a list of integers summed by an Aggregate method using a Lambda expression:
var mylist = new int[] { 3, 4, 5 };
var result = mylist.Aggregate((a, b) => a + b);
As I understand it, a Lambda expression can always be converted to a LINQ query. How would such a LINQ query look for my example?
EDIT: I understand .Sum may be better to add the numbers in my example. But I would really like to know how this Aggregate will look with a LINQ Query instead.
It already IS a LINQ query, Aggregate is a LINQ operator, i'm assuming what you meant was how it would look like in the LINQ comprehension syntax? The comprehension syntax only has a few built in features (select , where, multiple selects, groupby etc), it doesn't have all operators built in so when you need one of those (such as aggregate) you wrap it around parenthèses and keep going with the regular syntax. Since there is nothing there except aggregate it's not possible to give an example so i'll go from a different query:
var mylist = new int[] { 3, 4, 5, 6, 7, 8 };
var result = mylist
.Where(item=>item %2 == 0)
.Aggregate((a, b) => a + b);
var ComprehensiveResult =
(from item in mylist
where item % 2 == 0
select item)
.Aggregate((a, b) => a + b);
Comprehensive syntax is more of a "LINQ for people coming from SQL introduction", there's nothing you can do in it that you can't do with plain using the operators but the reverse isn't true as not all operators have built in replacements. The only thing that comes to mind where Comprehensive syntax is better (aside from personal taste) is multiple selects to generate a cartesian product which is much harder to maintain in plain method syntax.
In this case Aggregate function adds numbers each other. So, the equivalent function is SUM:
var qry = mylist.Sum(x=>x);
or
var qry = (from n in mylist select n).Sum();
[EDIT]
OP has added extra information to the question without informing me about that.
Yes, it's possible to "convert" Aggregate function into linq query, but extension method is needed. See this article: Cumulating values with LINQ
I want to write
CompareInfo myCompIntl = CompareInfo.GetCompareInfo( "es-ES" );
var SharedYomi = from ObjA in ClassListA
join ObjB in ClassListB
where CompareInfo.Compare(ObjA.Name, ObjB.Name) == 0
select new {stringA = stringA, string = string};
Linq forces me to write join with equals. I can not pass in a Boolean evaluation.
How can I do that?
You cannot write that using the LINQ lambda query syntax. The join keyword requires you to specify exactly two properties that are compared using the equals keyword, because this maps to the first overload of Join that uses the default comparer to compare keys.
However, there is an overload of Join that accepts an IEqualityComparer that will probably work for you, you just need to use method query syntax.
Since you sound like you're not familiar with the method syntax, here's a good starting article from MSDN:
http://msdn.microsoft.com/en-us/library/vstudio/bb397947.aspx
But, basically, the syntax you think of as "LINQ" is just one way to refer to the LINQ extensions, and is really just syntactic sugar around the IEnumerable extension methods that implement LINQ. So, for example, the query:
from x in y where x.IsActive orderby x.Name select x
it basically identical to
y.Where(x => x.IsActive).OrderBy(x => x.Name).Select(x => x);
For the most part, each query clause maps to a particular overload of a particular IEnumerable method, but those methods have a number of other overloads that take different numbers and types of parameters.
The Join methods are a bit complex, because they take two sequences as input and let you combine individual elements of them using expressions, but the idea is exactly the same. A typical join would look like this:
from x in y
join a in b on x.Id equals a.ParentId
select new { x.Id, x.Name, a.Date }
becomes
y.Join(
b,
x => x.Id,
a => a.ParentId,
(x, a) => new { x.Id, x.Name, a.Date });
This will join a.ParentId and x.Id using the default comparison for their data type (int, string, whatever). The compiler directly translates the query syntax into method syntax, so the two behave exactly the same. (Nitpicking my own answer: Technically, the methods are on the Enumerable class, so you are really calling Enumerable.Join. But as they were implemented as extension methods, you can call them either way and the compiler will figure it out.)
In your case, what you need is to pass in a different comparison method, so you can call string.Compare with the explicit encoding. The other overload of Join lets you supply an implementation of IEqualityComparer<T> to use instead of the default. This will require you to implement IEqualityComparer<string> in a separate class, since there's no easy way to create an anonymous interface implementation (perhaps the only feature I miss from Java). For your example, you want something like this:
public class ComparerWithEncoding : IEqualityComparer<string>
{
private CompareInfo compareInfo
public ComparerWithEncoding ( string encoding )
{
this.compareInfo = CompareInfo.GetCompareInfo(encoding);
}
public bool Equals ( string a, string b )
{
return CompareInfo.Compare(a, b) == 0
}
public int GetHashCode(string a)
{
return a.GetHashCode();
}
}
classListA.Join(
ClassListB,
ObjA => ObjA.Name,
ObjB => ObjB.Name,
(ObjA, ObjB) => new { stringA = ObjA.Foo, stringB = ObjB.Bar },
new ComparerWithEncoding("es-ES"));
Using pubs
If I want to join using query syntax I would do this.
from a in db.authors
join ta in db.titleauthors on a.au_id equals ta.au_id
join t in db.titles on ta.title_id equals t.title_id
join s in db.sales on t.title_id = s.title_id
select new { a.au_lname, t.title1, s.qty }
Using method syntax
db.authors
.Join(db.titleauthors,
a => a.au_id,
ta => ta.au_id,
(a, ta) => new {a, ta})
.Join(db.titles,
z => z.ta.title_id,
t => t.title_id,
(z, t) => new { z.a, z.ta, t })
.Join(db.sales,
z => z.t.title_id,
s => s.title_id,
(z, s) => new { z.a, z.ta, z.t, s })
.Select(z => new { z.a.au_lname, z.t.title1, z.s.qty })
I was wondering if there was an elegant way of dealing with this line
(z, X) => new { z.Y1, z.Y2, z.Y3... , X }
maybe something like
(z, X) => z.push(X)
so I don't have to write everything out.
Does something like that exist or is possible?
No. Basically query expressions exist in order to keep this stuff away from you. There's no particularly simple way of mimicking transparent identifiers.
I find that when you hit transparent identifiers, it's almost always cleaner to use query expression syntax. It's definitely worth knowing both, as very simple queries are cleaner using method syntax, but the more complicated the query, the more likely it is to be easier to read using query expressions.
That's assuming it can all be represented with method expressions, of course. Don't forget you can break up queries into separate statements without changing the meaning, so if you do need to call methods which don't have query expression equivalents, I sometimes find it best to separate it out like this:
var foo = from x in y
join a in b on x.Z equals a.Z
select new { a, x };
var bar = foo.Skip(5)
.Take(10)
.ToList();
I find that cleaner than just using brackets to mush the two syntax forms together.
I've been following with great interest the converstaion here:
Construct Query with Linq rather than SQL strings
with regards to constructing expression trees where even the table name is dynamic.
Toward that end, I've created a Extension method, addWhere, that looks like:
static public IQueryable<TResult> addWhere<TResult>(this IQueryable<TResult> query, string columnName, string value)
{
var providerType = query.Provider.GetType();
// Find the specific type parameter (the T in IQueryable<T>)
var iqueryableT = providerType.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == typeof(IQueryable<>), null).FirstOrDefault();
var tableType = iqueryableT.GetGenericArguments()[0];
var tableName = tableType.Name;
var tableParam = Expression.Parameter(tableType, tableName);
var columnExpression = Expression.Equal(
Expression.Property(tableParam, columnName),
Expression.Constant(value));
var predicate = Expression.Lambda(columnExpression, tableParam);
var function = (Func<TResult, Boolean>)predicate.Compile();
var whereRes = query.Where(function);
var newquery = whereRes.AsQueryable();
return newquery;
}
[thanks to Timwi for the basis of that code]
Which functionally, works.
I can call:
query = query.addWhere("CurUnitType", "ML 15521.1");
and it's functionally equivalent to :
query = query.Where(l => l.CurUnitType.Equals("ML 15521.1"));
ie, the rows returned are the same.
However, I started watching the sql log, and I noticed with the line:
query = query.Where(l => l.CurUnitType.Equals("ML 15521.1"));
The Query generated is:
SELECT (A bunch of columns)
FROM [dbo].[ObjCurLocView] AS [t0]
WHERE [t0].[CurUnitType] = #p0
whereas when I use the line
query = query.addWhere("CurUnitType", "ML 15521.1");
The query generated is :
SELECT (the same bunch of columns)
FROM [dbo].[ObjCurLocView] AS [t0]
So, the comparison is now happening on the client side, instead of being added to the sql.
Obviously, this isn't so hot.
To be honest, I mostly cut-and-pasted the addWhere code from Timwi's (slightly different) example, so some of it is over my head. I'm wondering if there's any adjustment I can make to this code, so the expression is converted into the SQL statement, instead of being determined client-side
Thanks for taking the time to read through this, I welcome any comments, solutions, links, etc, that could help me with this. And of course if I find the solution through other means, I'll post the answer here.
Cheers.
The big problem is that you're converting the expression tree into a delegate. Look at the signature of Queryable.Where - it's expressed in expression trees, not delegates. So you're actually calling Enumerable.Where instead. That's why you need to call AsQueryable afterwards - but that doesn't do enough magic here. It doesn't really put it back into "just expression trees internally" land, because you've still got the delegate in there. It's now wrapped in an expression tree, but you've lost the details of what's going on inside.
I suspect what you want is this:
var predicate = Expression.Lambda<Func<TResult, Boolean>>
(columnExpression, tableParam);
return query.Where(predicate);
I readily admit that I haven't read the rest of your code, so there may be other things going on... but that's the core bit. You want a strongly typed expression tree (hence the call to the generic form of Expression.Lambda) which you can then pass into Queryable.Where. Give it a shot :)