I am working with a similar problem Question 222511 I need to use MemberInit expression so that I can just add them to the constructor ... I am trying to insert John Skeet's answer , but I ran into a big difference in performance. Here are some of the code:
// Method A: // This work good, is fast and returns an un-executed query... DataContext.LoanNote.Join<LoanNote, Customer, int, LoanNote>( DataContext.Customers, loanNote => loanNote.PrimaryCustomerNumber, customer => customer.CustomerNumber, (LoanNote loanNote, Customer customer) => new LoanNote() { AccountFeeBillAmount = loanNote.AccountFeeBillAmount, AccountOpenDate = loanNote.AccountOpenDate, // This goes on and on... PrimaryCustomer = customer }); // Method B: // This on the other hand is a lot slower and I am not sure why... var resultSelector = BuildJoinResultSelector<LoanNote, Customer, LoanNote("PrimaryCustomer").Compile(); DataContext.LoanNote.Join<LoanNote, Customer, int, LoanNote>( DataContext.Customers, loanNote => loanNote.PrimaryCustomerNumber, customer => customer.CustomerNumber, resultSelector); // The build MemberInitExpression method... private static Expression<Func<TOuter, TInner, TResult>> BuildJoinResultSelector<TOuter, TInner, TResult>(string propertyName) where TResult : class { var result = default(Expression<Func<TOuter, TInner, TResult>>); var resultType = typeof(TResult); var outerType = typeof(TOuter); var innerType = typeof(TInner); var outer = Expression.Parameter(outerType, "outer"); var inner = Expression.Parameter(innerType, "inner"); var bindings = new List<MemberBinding>(); foreach (var property in resultType.GetProperties()) { if (property.CanRead == false) { continue; } else if (property.CanWrite == false) { continue; } else if (property.Name == propertyName) { var condition = Expression.Condition(Expression.Equal(inner, Expression.Constant(null)), Expression.New(innerType), inner); bindings.Add(Expression.Bind(property, condition)); } else { bindings.Add(Expression.Bind(property, Expression.Property(outer, property))); } } var memberInit = Expression.MemberInit(Expression.New(resultType), bindings); result = Expression.Lambda<Func<TOuter, TInner, TResult>>(memberInit, outer, inner); return result; }
performance c # lambda linq
bytebender
source share