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)