简体   繁体   English

添加到Lambda Expression并使用Entity Framework

[英]Adding to Lambda Expression and work with Entity Framework

If I want retrieve more columns with an already existing lambda tree expression like below, how would I do that? 如果我想要检索更多列已经存在的lambda树表达式,如下所示,我该怎么做? This works with Entity Frameworks and want it to still work. 这适用于实体框架,并希望它仍然有效。

Expression<Func<DivisionTeam, DirectorTeamModel>> columns= (d) => new DirectorTeamModel
{
    Id = d.Id,
    TeamId = d.Team.Id
};

if (criteria.Template == ExportTemplate.Import || criteria.Template == ExportTemplate.Default)
{
    // Retrieve additional columns from "columns" expression tree
}

return _divisionTeamsRepository.GetPagedResults(criteria.Page, criteria.PageSize, @where.Expand(), string.Format("{0} {1}", criteria.SortOrder, criteria.SortDirection), columns);

Given two "selector" expressions, you've to take the bindings from their MemberInitExpression and create a new expression using all the bindings. 给定两个“selector”表达式,您将从其MemberInitExpression获取绑定并使用所有绑定创建一个新表达式。 But this expression isn't going to work, since it uses two different parameter expressions for one single parameter. 但是这个表达式不起作用,因为它为一个参数使用两个不同的参数表达式。 We need to fix that too. 我们也需要解决这个问题。

Given... 鉴于...

Expression<Func<TSource, TResult>> left = ... // columns
Expression<Func<TSource, TResult>> right = ... // more columns

...take the bindings... ......拿绑定......

var leftInit = left.Body as MemberInitExpression;
var rightInit = right.Body as MemberInitExpression;

var bindings = leftInit.Bindings.Concat(rightInit.Bindings);

...create a new expression... ......创造一个新的表达......

var result = Expression.Lambda<Func<TSource, TResult>>(
    Expression.MemberInit(Expression.New(typeof(TResult)), bindings), ???);

...BUT, need single parameter... ...但是,需要单个参数......

var binder = new ParameterBinder(left.Parameters[0], right.Parameters[0]);
var bindings = binder.Visit(leftInit.Bindings.Concat(rightInit.Bindings));

// now, just use right.Parameters[0] as parameter...

And, replacing parameters works well using an expression visitor: 并且,使用表达式访问者更换参数效果很好:

class ParameterBinder : ExpressionVisitor
{
    readonly ParameterExpression parameter;
    readonly Expression replacement;

    public ParameterBinder(ParameterExpression parameter, Expression replacement)
    {
        this.parameter = parameter;
        this.replacement = replacement;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node == parameter)
            return replacement;

        return base.VisitParameter(node);
    }
}

Abstracting this plumbing stuff works quite well. 抽象这个管道的东西工作得很好。 In fact, you can just use an existing library (spoiler: I'm the author), which should lead to something like that: 事实上,你可以使用现有的库 (剧透:我是作者),这应该会导致类似的东西:

var merged = columns.Apply(moreColumns);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM