在知道 EntityFramework 包含用于检索 属性 的表达式的对象上设置 属性
Setting property on object knowing the EntityFramework include expression that was used to retrieve that property
有没有一种方法可以设置实体对象导航属性,知道用于在对象上包含此导航 属性 的表达式?
即
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
class 方法生成 属性 setter。
但是在使用 EF 时不需要这样做,因为 DbEntityEntry<TEntity>
class provides a Reference
method with the exact same argument, which returns a DbReferenceEntry<TEntity, TProperty>
instance, which in turn has 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;
更新: 以上适用于简单的 (a.k.a. reference) 导航属性,不适用于集合。以下是如何从 属性 访问器表达式构建 属性 setter:
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);
这样您也可以 get/set 集合属性。添加到集合中仍然是一个问题,但那是另一回事了。
有没有一种方法可以设置实体对象导航属性,知道用于在对象上包含此导航 属性 的表达式?
即
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
class 方法生成 属性 setter。
但是在使用 EF 时不需要这样做,因为 DbEntityEntry<TEntity>
class provides a Reference
method with the exact same argument, which returns a DbReferenceEntry<TEntity, TProperty>
instance, which in turn has 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;
更新: 以上适用于简单的 (a.k.a. reference) 导航属性,不适用于集合。以下是如何从 属性 访问器表达式构建 属性 setter:
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);
这样您也可以 get/set 集合属性。添加到集合中仍然是一个问题,但那是另一回事了。