生成动态选择lambda表达式

时间:2013-03-20 15:19:13

标签: entity-framework lambda linq-to-entities expression-trees

我对表达树有些新意,我只是不太了解一些事情。

我需要做的是发送值列表并从这些值中选择实体的列。所以我会拨打这样的电话:

DATASTORE<Contact> dst = new DATASTORE<Contact>();//DATASTORE is implemented below.
List<string> lColumns = new List<string>() { "ID", "NAME" };//List of columns
dst.SelectColumns(lColumns);//Selection Command

我希望将其翻译成这样的代码(Contact是使用EF4的实体):

Contact.Select(i => new Contact { ID = i.ID, NAME = i.NAME });

所以我想说我有以下代码:

public Class<t> DATASTORE where t : EntityObject
{
    public Expression<Func<t, t>> SelectColumns(List<string> columns)
    {
        ParameterExpression i = Expression.Parameter(typeof(t), "i");
        List<MemberBinding> bindings = new List<MemberBinding>();

        foreach (PropertyInfo propinfo in typeof(t).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (columns.Contains(propinfo.Name))
            {
                MemberBinding binding = Expression.Bind(propinfo, Expression.Property(i, propinfo.Name));
                bindings.Add(binding);
            }
        }

        Expression expMemberInit = Expression.MemberInit(Expression.New(typeof(t)), bindings);
        return Expression.Lambda<Func<t, t>>(expMemberInit, i);
    }

当我运行上面的代码时,我收到以下错误:

  

无法在LINQ to Entities查询中构造实体或复杂类型“Contact”。

我查看了查询的正文,它发出了以下代码:

{i => new Contact() {ID = i.ID, NAME = i.NAME}}

我很确定我应该能够构建一个新实体,因为我明确地将这一行写成了一个测试,看看是否可以这样做:

.Select(i => new Contact{ ID = i.ID, NAME = i.NAME })

这很有效,但我需要动态构建选择。

我尝试反编译直接查询(我第一次查看低级代码)并且我无法完全翻译它。我输入的高级代码是:

Expression<Func<Contact, Contact>> expression = z => 
                    new Contact { ID = z.ID, NAME = z.NAME };

更改反编译器中使用的框架我得到了这段代码:

ParameterExpression expression2;
Expression<Func<Contact, Contact>> expression = 
   Expression.Lambda<Func<Contact, Contact>>
      (Expression.MemberInit(Expression.New((ConstructorInfo) methodof(Contact..ctor),
         new Expression[0]), new MemberBinding[] { Expression.Bind((MethodInfo) 
            methodof(Contact.set_ID), Expression.Property(expression2 = Expression.Parameter(typeof(Contact), "z"), (MethodInfo) 
            methodof(Contact.get_ID))), Expression.Bind((MethodInfo) 
            methodof(Contact.set_NAME), Expression.Property(expression2, (MethodInfo) 
               methodof(Contact.get_NAME))) }), new ParameterExpression[] { expression2 
        });

我看了好几个地方试图理解这个但我还没有完全理解。有人可以帮忙吗?

这些是我看过的地方:

1 个答案:

答案 0 :(得分:1)

当我上次将结果投影到未映射的类(非实体)并且它工作时,其他所有内容都与代码中的相同。您确定不是像.Select(i =&gt; new Contact {ID = i.ID,NAME = i.NAME})这样的动态查询吗?