动态表达式的行为与“静态”表达式不同

时间:2019-04-25 15:36:14

标签: c# lambda nhibernate expression

我正在创建一个动态投影(选择)lambda表达式,并将其与Linq一起用于NHibernate。看起来等效的静态表达式没有相同的表现。静态表达式已正确地转换为sql的外部联接,但是动态表达式正在使用多个from语句(无联接)进行转换。这些表达式似乎是等效的。我需要找到一种方法来阐明表达式为何不同的原因,或者更好地理解表达式从编译时编译到运行时“编译”的不同之处-猜测这与遍历属性有关,但这仅仅是一个问题。猜。

public static class Dyna
{
    public static Expression<Func<Tsrc, Tdto>> SelectProps<Tsrc, Tdto>(List<string> props)
    {
        Type typeEnt = typeof(Tsrc);
        Type typeDto = typeof(Tdto);
        var ctor = Expression.New(typeDto);
        ParameterExpression parameter = Expression.Parameter(typeEnt, "x");
        var propertiesDto = typeDto.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        var tprops = typeEnt.GetProperties();
        var tflds = typeEnt.GetFields();

        var memberAssignments = propertiesDto.Select(p =>
        {
            var PPath = GetPropertyPath(p);

            if (PPath != null)
            {
                if (props.Contains(p.Name))
                {
                    var mem = GetMemberExpression(CreateExpression(typeEnt, PPath));

                    return Expression.Bind(p, mem);
                }
                else { return null; }
            }
            else
            {
                return null;
            }
        });


        var memexps = memberAssignments.Where(m => m != null);

        var memberInit = Expression.MemberInit(ctor, memexps);

        return Expression.Lambda<Func<Tsrc, Tdto>>(memberInit, parameter);
    }

    public static MemberExpression GetMemberExpression(Expression expression)
    {
        if (expression is MemberExpression)
        {
            return (MemberExpression)expression;
        }
        else if (expression is LambdaExpression)
        {
            var lambdaExpression = expression as LambdaExpression;
            if (lambdaExpression.Body is MemberExpression)
            {
                return (MemberExpression)lambdaExpression.Body;
            }
            else if (lambdaExpression.Body is UnaryExpression)
            {
                return ((MemberExpression)((UnaryExpression)lambdaExpression.Body).Operand);
            }
        }
        return null;
    }

    public static LambdaExpression CreateExpression(Type type, string propertyName)
    {
        var param = Expression.Parameter(type, "x");
        Expression body = param;
        foreach (var member in propertyName.Split('.'))
        {
            body = Expression.PropertyOrField(body, member);
        }
        return Expression.Lambda(body, param);
    }

静态表达式代码

    var conn = this.Connection.ConnectionString;

    // NH Session
    using( var Session = SetupNHConfig(conn).OpenSession())
    {   
        // NH Linq Query
        var evtq = Session.Query<Event>();

        var res = evtq.Select(x => new EventDto() {
            Id = x.Id,
            ProjectName = x.ProjectName, 
            EventName = x.EventName, 
            EventType = x.EventType.EventTypeName, 
            Status = x.EventStatus.EventStatusTypeName}
            );

        res.Dump();


        //x => new EventDto() {ProjectName = x.ProjectName, EventName = x.EventName, Status = x.EventStatus.EventStatusTypeName}

        res.ToList().Dump();
    }

生成的SQL

-- Generated by Static Expression
SELECT event0_.ProjectName AS col_0_0_, 
       event0_.EventName AS col_1_0_, 
       eventtype1_.EventTypeName AS col_2_0_, 
       eventstatu2_.EventStatusTypeName AS col_3_0_
FROM trg_eventmgr_Event event0_
     LEFT OUTER JOIN trg_eventmgr_EventType eventtype1_ ON event0_.EventType_id = eventtype1_.ID
     LEFT OUTER JOIN trg_eventmgr_EventStatusType eventstatu2_ ON event0_.EventStatus_id = eventstatu2_.ID;

-- Generated by Dynamic Expression
SELECT event0_.ID AS col_0_0_, 
       event0_.ProjectName AS col_1_0_, 
       event0_.EventName AS col_2_0_, 
       eventtype1_.EventTypeName AS col_3_0_, 
       eventstatu2_.EventStatusTypeName AS col_4_0_
FROM trg_eventmgr_Event event0_, 
     trg_eventmgr_EventType eventtype1_, 
     trg_eventmgr_EventStatusType eventstatu2_
WHERE event0_.EventType_id = eventtype1_.ID
      AND event0_.EventStatus_id = eventstatu2_.ID;

0 个答案:

没有答案