简体   繁体   中英

How do I get Expression<System.Func<TEntity, TEntity>> when I have an Expression?

I'm working on a generic PATCH method for a service.

public virtual void Patch ( int id, Delta<TEntityView> view )
{
    var type = typeof( TEntity );
    TEntity model = Activator.CreateInstance( type ) as TEntity;

    foreach( var changedProperty in view.GetChangedPropertyNames() )
    {
        var property = type.GetProperty( changedProperty );
        var propertyType = property.PropertyType;
        var retreived = view.TryGetPropertyValue( changedProperty, out object propval );

        if ( retreived && property != null )
        {
            property.SetValue( model, propval, null );
        }
    }

    UnitOfWork.Query<TEntity>( e => e.Id == id )
        .Update( m => model );
}

At the Update statement, I'm getting

System.Exception: 'Invalid Cast. The update expression must be of type MemberInitExpression.'

That method is defined in Entity Framework Plus ( https://entityframework-plus.net/ ):

#region Assembly Z.EntityFramework.Plus.EF6, Version=1.12.14.0, Culture=neutral, PublicKeyToken=59b66d028979105b
public static int Update<T>(this IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : class;

I changed my method as follows:

public virtual void Patch ( int id, Delta<TEntityView> view )
{
    var type = typeof( TEntity );
    var bindings = new List<MemberBinding>();

    foreach( var changedProperty in view.GetChangedPropertyNames() )
    {
        var property = type.GetProperty( changedProperty );
        var propertyType = property.PropertyType;
        var retreived = view.TryGetPropertyValue( changedProperty, out object propval );

        if ( retreived && property != null )
        {
            bindings.Add( Expression.Bind( type.GetMember( changedProperty )[0], Expression.Constant( propval ) ) );
        }
    }

    Expression ex = Expression.MemberInit( Expression.New( type ), bindings );

    // Expression <-- have this
    // Expression<Func<TModel, TModel>> updateFactory <-- need this

    UnitOfWork.Query<TEntity>( e => e.Id == id )
        .Update( ex );
}

Now, on the Update, I'm getting a red squiggly with the message: Argument 1: cannot convert from 'System.Linq.Expressions.Expression' to 'System.Linq.Expressions.Expression<System.Func<TEntity, TEntity>>'

I'm certain that I'm missing something small to make the magic work. What is it?

You did the hard part and it looks correct on first glance, what you want is to wrap it in lambda so the part like x => ex:

var parameter = Expression.Parameter(type,"x");
var lambda = Expression.Lambda<Func<TEntity,TEntity>>(ex, parameter);
UnitOfWork.Query<TEntity>( e => e.Id == id )
    .Update( lambda );

(written from memory so to be verified)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM