如何使用表达式树生成以下内容...
var people = context.Set(); var transactions = context.Set (); var dataview = people.Where( p => p.LastName == "Smith" ); var selection = dataview .Select( p => new { FirstName = p.FirstName, LastName = p.LastName, LastTransaction = transactions .Where( t => t.AuthorizedPersonId == p.Id ) .Max( t => t.TransactionDateTime ) } ); gReport.AutoGenerateColumns = true; gReport.DataSource = selection.ToList(); gReport.DataBind();
我正在尝试使用Ethan Brown 在这里提供的LinqRuntimeTypeBuilder解决方案,但在如何为LastTransaction子查询创建表达式以及如何将查询绑定到GridView方面苦苦挣扎.
这就是我到目前为止......
var people = context.Set(); var transactions = context.Set (); var dataview = people.Where( p => p.LastName == "Smith" ); var dynamicFields = new Dictionary (); dynamicFields.Add( "FirstName", typeof( string ) ); dynamicFields.Add( "LastName", typeof( string ) ); dynamicFields.Add( "LastTransaction", typeof( DateTime? ) ); Type dynamicType = Rock.Data.LinqRuntimeTypeBuilder.GetDynamicType( dynamicFields ); ParameterExpression sourceItem = Expression.Parameter( dataview.ElementType, "x" ); // Is this right? if if so how do I bind it to the dynamic field???? Expression > lastTransactionSelect = a => transactions.Where( t => t.AuthorizedPersonId == a.Id && t.TransactionDateTime.HasValue ).Max( t => t.TransactionDateTime.Value ); var bindings = new List (); bindings.Add( Expression.Bind( dynamicType.GetField( "FirstName" ), Expression.Property( sourceItem, dataview.ElementType.GetProperty( "FirstName" ) ) ) ); bindings.Add( Expression.Bind( dynamicType.GetField( "LastName" ), Expression.Property( sourceItem, dataview.ElementType.GetProperty( "LastName" ) ) ) ); bindings.Add( Expression.Bind( dynamicType.GetField( "LastTransaction" ), ??? ) ); Expression selector = Expression.Lambda( Expression.MemberInit( Expression.New( dynamicType.GetConstructor( Type.EmptyTypes ) ), bindings ), sourceItem ); var query = dataview.Provider.CreateQuery( Expression.Call( typeof( Queryable ), "Select", new Type[] { dataview.ElementType, dynamicType }, Expression.Constant( dataview ), selector ) ).AsNoTracking(); // Can't bind directly to the query since it's a DBQuery object gReport.DataSource = ???; gReport.DataBind();
如何为子查询创建表达式,然后将查询绑定到GridView的最佳方法是什么?
在使用Reflector来评估编译器如何生成linq语句之后,这里是我最终为子选择创建表达式的方法......
ParameterExpression transactionParameter = Expression.Parameter(typeof(FinancialTransaction), "t"); MemberExpression authorizedPersonIdProperty = Expression.Property(transactionParameter, "AuthorizedPersonId"); MemberExpression transactionDateTime = Expression.Property(transactionParameter,"TransactionDateTime"); MethodInfo whereMethod = GetWhereMethod(); MethodInfo maxMethod = GetMaxMethod(); var personIdCompare = new Expression[] { Expression.Constant(transactions), Expression.Lambda<Func<FinancialTransaction, bool>>( Expression.Equal(authorizedPersonIdProperty, Expression.Convert(idProperty, typeof(int?))), new ParameterExpression[] { transactionParameter } ) }; var transactionDate = Expression.Lambda<Func<FinancialTransaction, DateTime?>>( transactionDateTime, new ParameterExpression[] { transactionParameter } ); var lastTransactionDate = Expression.Call( null, maxMethod, new Expression[] { Expression.Call( null, whereMethod, personIdCompare ), transactionDate } ); ... bindings.Add( Expression.Bind( dynamicType.GetField( "LastTransaction" ), lastTransactionDate ) ); ... private MethodInfo GetWhereMethod() { Func<FinancialTransaction, bool> fake = element => default( bool ); Expression<Func<IEnumerable<FinancialTransaction>, IEnumerable<FinancialTransaction>>> lamda = list => list.Where( fake ); return ( lamda.Body as MethodCallExpression ).Method; } private MethodInfo GetMaxMethod() { Func<FinancialTransaction, DateTime?> fake = element => default( DateTime? ); Expression<Func<IEnumerable<FinancialTransaction>, DateTime?>> lamda = list => list.Max( fake ); return ( lamda.Body as MethodCallExpression ).Method; }