2017-06-29 48 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'表達式不兼容。 –