How to make an expression of an expression type a reference a reference type?

I wanted to store a collection of expressions accessing the properties of an object. For example:

class Entity
{
    public int Id { get; set; }
    public Entity Parent { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }        
    public decimal Value { get; set; }
    public bool Active { get; set; }
}

static void Main(string[] args)
{
    var list = new List<Expression<Func<Entity, object>>>();
    list.Add(e => e.Id);
    list.Add(e => e.Name);
    list.Add(e => e.Parent);
    list.Add(e => e.Date);
    list.Add(e => e.Value);
    list.Add(e => e.Active);

    StringBuilder b = new StringBuilder();
    list.ForEach(f => b.AppendLine(f.ToString()));

    Console.WriteLine(b.ToString());
    Console.ReadLine();
}

This code outputs:

e => Convert(e.Id)
e => e.Name
e => e.Parent
e => Convert(e.Date)
e => Convert(e.Value)
e => Convert(e.Active)

It adds Convertto type values.

In the end, I wanted to use these expressions with LINQ to SQL, I do not need to have this Convertin the expressions in order for them to be successfully translated into SQL.

How can i achieve this?

PS: expressions from this collection are later used as arguments to OrderByand methods ThenBy.

+4
source share
3 answers

If you create a function that generates a proeprty type, you can avoid the conversion:

private static LambdaExpression GetExpression<TProp>
                                    (Expression<Func<Entity, TProp>> expr)
{
    return expr;
}

list:

var list = new List<LambdaExpression>();
list.Add(GetExpression(e => e.Id));
list.Add(GetExpression(e => e.Name));

OrderBy ThenBy , .

LambdaExpression idExpr = list[0];
Type keyType = idExpr.ReturnType;

var orderByMethod = typeof(Queryable).GetMethods()
    .Single(m => m.Name == "OrderBy" && m.GetParameters().Length == 2)
    .MakeGenericMethod(typeof(Entity), keyType);

var ordered = (IQueryable<Entity>)
                  orderByMethod.Invoke(null, new object[] { source, idExpr });
+3

EF ,

public class Entity
{
    public int Id { get; set; }
    public Entity Parent { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public decimal Value { get; set; }
    public bool Active { get; set; }
}
public class EntityContext : DbContext
{
    public EntityContext()
        : base(new SqlCeConnection("Data Source=Database.sdf;Persist Security Info=False;"),
            contextOwnsConnection: true)
    {
        // Using a SQL Compact database as backend
    }
    public DbSet<Entity> Entities { get; set; }
}

linq

static void Main(string[] args)
{
    var list = new List<Expression<Func<Entity, object>>>();
    list.Add(e => e.Date);
    list.Add(e => e.Name);
    using (var c = new EntityContext())
    {
        //each time a new record is added
        var data = new Entity
        {
            Name = string.Format("Data{0}", c.Entities.Count()),
            Date = DateTime.Now
        };
        c.Entities.Add(data);
        c.SaveChanges();

        // sort by date
        foreach (var e in c.Entities.OrderBy(list.First().Compile()))
            Console.WriteLine(string.Format("{0} - {1}", e.Name, e.Date));

        // sort by name .. in reverse
        foreach (var e in c.Entities.OrderByDescending(list.Last().Compile()))
            Console.WriteLine(string.Format("{0} - {1}", e.Name, e.Date));

    }
    Console.ReadLine();
}

.

UPDATE LINQ to SQL: SQL Server , , OrderBy: .

: " ".

+1

Alex. , , :

Queryable.OrderBy, LINQ OrderBy SQL, . , Expression<Func<TEntity, object>>, e => Convert(e.Field), LINQ InvalidOperationException, Cannot order by type 'System.Object'.

Enumerable.OrderBy, LINQ OrderBy SQL-, , , . Func<TEntity, object>.

, :

  • LINQ, SQL-, ; .

In my particular case, sorting is the last operation to perform, and I don’t see much harm if I order the result set in the program memory ... I am not going to expect that a huge amount of data will be returned ...

Although in the more common case, it is probably even better to do all the possible operations in the database layer ...

PS: SO: Request a linq request - private discussion ...

0
source

All Articles