Generate dynamic select lambda expressions

entity-framework expression-trees lambda linq-to-entities

Question

I'm still learning a lot about expression trees, so I have a few questions.

Sending in a list of values and choosing the columns for an entity from that list is what I need to accomplish. Therefore, I would dial 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

That should be converted to code like this (Contact is a company using the EF4):

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

Let's suppose I have the code below:

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

I received the following problem when I executed the code above:

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

The query's body emitted the following code, which I noticed when I looked at it:

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

Because I specifically created this line as a test to check whether this could be done, I am quite certain that I should be able to generate the new entity:

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

This method works, however I still need to dynamically generate the select.

I attempted to decompile a straight query (this was my first time looking at the low level code), but I was unable to fully translate it. I input the high level code, which is:

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

Changing the decompiler's framework results in the following 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've looked in a lot of different places to attempt to comprehend this, but I still don't completely get it. Can anyone assist?

I searched the following locations, among others:

  • zzz-72 zzz I want to accomplish this precisely, however my decompiled code lacks Expression. Call.
  • MemberInit msdn
  • Expression Property msdn
  • zzz-91 zzz Although it's near, it seems to be doing the same action as if I were to just choose data from a query.
  • 98 zzzz — The solution provided here is precisely what I'm trying to do, however I'm not sure how to convert the decompiled code to C#.
1
3
5/23/2017 12:15:28 PM

Popular Answer

The last time I did it, I projected the result to an unmapped class (not an entity), and it worked; the rest of the code was the same as yours. Are you certain that the query is not dynamic? It works with Select(i => new Contact, ID = i.ID, NAME = i.NAME).

1
3/21/2013 2:02:00 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow