2017-06-29 45 views
0

是否有一种方法可以设置实体对象导航属性,以了解用于将对象导航属性包含在内的表达式?在知道EntityFramework的对象上设置属性包含用于检索该属性的表达式

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

+1

你能定义什么''_repo'''是? – RemedialBear

+0

试图让它更清楚一点,只需使用DbContext实例 – weagle08

+1

抱歉,您能否在此问题中添加更多上下文?目前还不清楚你将如何使用它。是否定义了''''T'',或者您是否试图根据您所加载的实体的包含属性来生成一个通用对象? – RemedialBear

回答

3

鉴于Expression<Func<T, object>>有效期为Include,有可能使用Expression类的方法来生成的属性设置。

但是没有必要做,与EF工作时,因为DbEntityEntry<TEntity>类提供了一个Reference方法具有完全相同的参数,它返回一个DbReferenceEntry<TEntity, TProperty>实例,这反过来又CurrentValue属性,该属性可以用来GET并设置的导航属性值。

的使用可能是这样的:

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; 

更新:上述作品简单(又名参考)导航属性而不是收藏。下面是如何从属性访问表达构建一个属性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); 

这样,您就可以得到/集收藏性为好。加入收藏仍然是一个问题,但这是另一回事。

+0

好的,如果'''.CurrentValue'''是一个List <>?我可以投下并添加一个.Add吗? – weagle08

+0

您是否也可以举一个如何使用Expression类方法创建属性设置器的示例?在实际的代码中,_dbContext隐藏在存储库模式后面,所以我需要能够直接处理返回的实体对象来修改值,然后调用我们的工作单元保存更改。 – weagle08

+0

那么,我假设你要求简单的(a.k.a.参考)属性。对于收藏它更复杂。它需要'Collection'方法,这不幸需要'Expression >',这与'Include'表达式不兼容。 –