I am trying to build a lambda expression, containing two assignments (as shown further down), that I can then pass to a Queryable.Select() method.
I am trying to pass a string variable into a method and then use that variable to build up the lambda expression so that I can use it in a LINQ Select query.
My reasoning behind it is that I have a SQL Server datasource with many column names, I am creating a charting application that will allow the user to select, say by typing in the column name, the actual column of data they want to view in the y-axis of my chart, with the x-axis always being the DateTime. Therefore, they can essentially choose what data they chart against the DateTime value (it’s a data warehouse type app).
I have, for example, a class to store the retrieved data in, and hence use as the chart source of:
public class AnalysisChartSource
{
public DateTime Invoicedate { get; set; }
public Decimal yValue { get; set; }
}
I have (purely experimentaly) built an expression tree for the Where clause using the String value and that works fine:
public void GetData(String yAxis)
{
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
var data = this.FunctionOne().AsQueryable<AnalysisChartSource>();
//just to get some temp data in....
ParameterExpression pe = Expression.Parameter(typeof(AnalysisChartSource), "p");
Expression left = Expression.MakeMemberAccess(pe,
typeof(AnalysisChartSource).GetProperty(yAxis));
Expression right = Expression.Constant((Decimal)16);
Expression e2 = Expression.LessThan(left, right);
Expression expNew = Expression.New(typeof(AnalysisChartSource));
LambdaExpression le = Expression.Lambda(left, pe);
MethodCallExpression whereCall = Expression.Call(
typeof(Queryable), "Where", new Type[] { data.ElementType },
data.Expression,
Expression.Lambda<Func<AnalysisChartSource, bool>>(e2, new ParameterExpression[] { pe }));
}
}
However……I have tried a similar approach for the Select statement, but just can’t get it to work as I need the Select() to populate both X and Y values of the AnalysisChartSource class, like this:
.Select(c => new AnalysisChartSource
{ Invoicedate = c.Invoicedate, yValue = c.yValue}).AsEnumerable();
How on earth can I build such an expression tree….or….possibly more to the point…..is there an easier way that I have missed entirely?
select (s => new SelectListItem { Value = s. ID. ToString(), Text = s.Name} ); select (s => new SelectListItem { Value = s.ID + "", Text = s.Name} );
When choosing a lambda value, the goal is to strike the right balance between simplicity and training-data fit: If your lambda value is too high, your model will be simple, but you run the risk of underfitting your data. Your model won't learn enough about the training data to make useful predictions.
So performance-wise, there's no difference whatsoever between the two. Which one you should use is mostly personal preference, many people prefer lambda expressions because they're shorter and more concise, but personally I prefer the query syntax having worked extensively with SQL.
The => operator can be used in two ways in C#: As the lambda operator in a lambda expression, it separates the input variables from the lambda body. In an expression body definition, it separates a member name from the member implementation.
I find that the best way to work out how to build expression trees is to see what the C# compiler does. So here's a complete program:
using System;
using System.Linq.Expressions;
public class Foo
{
public int X { get; set; }
public int Y { get; set; }
}
class Test
{
static void Main()
{
Expression<Func<int, Foo>> builder =
z => new Foo { X = z, Y = z };
}
}
Compile that, open the results in Reflector and set the optimisation to .NET 2.0. You end up with this generated code for the Main method:
ParameterExpression expression2;
Expression<Func<int, Foo>> expression =
Expression.Lambda<Func<int, Foo>>(
Expression.MemberInit(
Expression.New((ConstructorInfo) methodof(Foo..ctor), new Expression[0]),
new MemberBinding[] { Expression.Bind((MethodInfo) methodof(Foo.set_X),
expression2 = Expression.Parameter(typeof(int), "z")),
Expression.Bind((MethodInfo) methodof(Foo.set_Y),
expression2) }
),
new ParameterExpression[] { expression2 });
Basically, I think Expression.MemberInit
is what you're after.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With