3
votes

I am somewhat new to expression trees and I just don't quite understand some things.

What I need to do is send in a list of values and select the columns for an entity from those values. So I would make a call something like this:

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

I want that to be translated into code like this (Contact is an entity using the EF4):

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

So let's say I have the following code:

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);
    }

When I ran the above code I got the following error:

The entity or complex type 'Contact' cannot be constructed in a LINQ to Entities query.

I looked at the body of the query and it emitted the following code:

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

I am pretty sure that I should be able to construct the a new entity because I wrote this line explicitly as a test to see if this could be done:

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

This worked, but I need to construct the select dynamically.

I tried decompiling a straight query(first time I have looked at the low level code) and I can't quite translate it. The high level code that I entered is:

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

Changing the framework used in the decompiler I get this code:

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 
        });

I have looked several places to try and understand this but I haven't quite gotten it yet. Can anyone help?

These are some places that I have looked:

1

1 Answers

1
votes

When I did it last time I projected result to not mapped class (not entity) and it worked, everything else was the same as in your code. Are you sure that not dynamic query like .Select(i => new Contact{ ID = i.ID, NAME = i.NAME }) works?