添加到Lambda表达式并使用实体框架 [英] Adding to Lambda Expression and work with Entity Framework

查看:127
本文介绍了添加到Lambda表达式并使用实体框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我想要使用已有的lambda树表达式获取更多列,如下所示,我该怎么做?这与实体框架一起工作,并希望它仍然可以工作。

 表达式&FunC< DivisionTeam,DirectorTeamModel>>列=(d)=> new DirectorTeamModel 
{
Id = d.Id,
TeamId = d.Team.Id
};

if(criteria.Template == ExportTemplate.Import || criteria.Template == ExportTemplate.Default)
{
//从列中获取其他列表达式树
}

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


解决方案

给定两个选择器表达式,你必须从 MemberInitExpression 中获取绑定,并使用所有绑定创建一个新的表达式。但是这个表达式不会有效,因为它对于一个参数使用两个不同的参数表达式。我们需要解决这个问题。



给定...

 表达< Func< TSource,TResult>> left = ... // columns 
Expression< Func< TSource,TResult>> right = ... //更多列

...采取绑定...

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

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

...创建一个新的表达式...


$ b $ (
Expression.MemberInit(Expression.New(typeof(TResult)),绑定),
$ ???);

...但是,需要单一参数...

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

//现在,只需使用right.Parameters [0]作为参数...

而且,使用表达式访问者替换参数很好:

  class ParameterBinder:ExpressionVisitor 
{
只读ParameterExpression参数;
只读表达式替换;

public ParameterBinder(ParameterExpression参数,表达式替换)
{
this.parameter = parameter;
this.replacement = replacement;
}

protected override表达式访问参数(ParameterExpression node)
{
if(node == parameter)
return replace;

返回base.VisitParameter(node);
}
}

抽象这个管道工作效果很好。事实上,您只能使用现有的图书馆(扰流:我是作者),这应该导致类似的东西:

  var merged = columns.Apply(moreColumns); 


If I want retrieve more columns with an already existing lambda tree expression like below, how would I do that? 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. 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);

这篇关于添加到Lambda表达式并使用实体框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆