在对象上设置属性知道实体框架包括用于检索该属性的表达式



有没有办法设置实体对象导航属性知道用于在对象上包含此导航属性的表达式?

即。

public class MyGenericBusinessLogic<T> {
    private readonly DbContext _dbContext;

    public MyGenericBusinessLogic(DbContext dbContext) {
       _dbContext = dbContext;
    }
    public U AddItem<U>(int parentId, Expression<Func<T,object>> property, U item) {
        T entity = _dbContext.[DbSet].Queryable.Include(t => t.Property).SingleOrDefault(e => e.id == id);
        //HELP NEEDED HERE
        //now how do i add the ```U item``` to the ```T entity```?
        _dbContext.SaveChanges();
        return item;
    }
}

因此,鉴于您在t => t.Property上方具有表达式,是否可以将该属性的值设置为U item

entity.[Property] = item

给定的 Expression<Func<T, object>>,对Include有效,可以使用Expression类方法生成属性设置器。

但是,在与EF一起工作时无需这样做,因为DbEntityEntry<TEntity>类提供了具有完全相同参数的Reference方法,该方法返回DbReferenceEntry<TEntity, TProperty>实例,该实例又具有CurrentValue属性,该属性可用于获取并设置导航属性值。

用法可能是这样:

Expression<Func<T, object>> property = t => t.Property;
T entity = _dbContext.Queryable.Include(property).SingleOrDefault(e => e.id == id);
// Get the property value
var oldValue = _dbContext.Entry(entity).Reference(property).CurrentValue;
// Set the property value
_dbContext.Entry(entity).Reference(property).CurrentValue = newValue;

更新:以上适用于简单(又称参考(导航属性,而不是集合。这是您可以从属性登录器表达式构建属性设置程序的方式:

static Expression<Action<T, object>> MakeSetter<T>(Expression<Func<T, object>> property)
{
    var member = (MemberExpression)property.Body;
    var source = property.Parameters[0];
    var value = Expression.Parameter(typeof(object), "value");
    var body = Expression.Assign(member, Expression.Convert(value, member.Type));
    return Expression.Lambda<Action<T, object>>(body, source, value);
}

和用法:

Expression<Func<T, object>> property = t => t.Property;
T entity = _dbContext.Queryable.Include(property).SingleOrDefault(e => e.id == id);
// Get the property value
var oldValue = property.Compile()(entity);
// Set the property value
MakeSetter(property).Compile()(entity, newValue);

这样,您也可以获得/设置收集属性。不过,添加收集仍然是一个问题,但这是另一个故事。

最新更新