views:

64

answers:

1

I'm working with the new EF4 CTP4 although I don't think this has much to do with that. I am trying to set up a system where I can add auditable fields for our database automatically. What I'm trying to do is combine the following two expressions

a => new
{
    a.CreatedBy,
    a.CreatedTime,
    a.UpdatedBy,
    a.UpdatedTime
}

and

a => new
{
    a.Id,
    a.Name,


}

so the result is equivalant to

a => new
{
    a.Id,
    a.Name,
    a.CreatedBy,
    a.CreatedTime,
    a.UpdatedBy,
    a.UpdatedTime
}

the result I need to be an Expression<Func<T, object>>. I've been poking around and tried several things with Expression.Invoke and Expression.And(andalso) and haven't found anything that is working for me.

I'm not quite sure if this is possible but any help would be appreciated.

A: 

I don't think you can simply 'merge' two expressions. But you can use alternate API to create mappings with EntityMap.

public static class MapBuilder
{
    public static Expression<Func<T, object>> GetMap<T>(Expression<Func<T, object>> func) where T: IAuditable
    {
        var body = func.Body as NewExpression;

        var param = Expression.Parameter(typeof(T), "o");

        var propertyAccessExprs = new List<Expression>();

        foreach (MemberInfo member in body.Members)
        {
            propertyAccessExprs.Add(Expression.Property(param, member.Name));
        }

        var props = typeof(IAuditable).GetProperties();

        foreach (PropertyInfo prop in props)
        {
            propertyAccessExprs.Add(Expression.Property(param, prop.Name));
        }

        var columnMappins = new List<Expression>();

        foreach (var access in propertyAccessExprs)
        {
            columnMappins.Add(Expression.Call(typeof(EntityMap).GetMethod("Column", new Type[] {typeof(Object)}), Expression.Convert(access, typeof(Object))));
        }

        var RowExpr = Expression.Call(typeof(EntityMap).GetMethod("Row"), Expression.NewArrayInit(typeof(EntityMapColumn), columnMappins));

        var result = Expression.Lambda<Func<T, object>>(RowExpr, param);

        return result;
    }
}

The usage is

 var builder = new ModelBuilder();
            builder.Entity<SimpleAuditableObject>()
                .HasKey(o => o.Id)
                .MapSingleType(MapBuilder.GetMap<SimpleAuditableObject>(o => new { o.Id, o.Name }));

Where

public interface IAuditable
{
    int CreatedBy { get; set; }
    DateTime CreatedTime { get; set; }
    int UpdatedBy { get; set; }
    DateTime UpdatedTime { get; set; }
}

public class SimpleAuditableObject : IAuditable
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int CreatedBy { get; set; }
    public DateTime CreatedTime { get; set; }
    public int UpdatedBy { get; set; }
    public DateTime UpdatedTime { get; set; }
}

HTH.

Yury Tarabanko
This worked perfectly. I really appreciate it. genius
SnyderJK
You are welcome :)
Yury Tarabanko