我正在嘗試為使用 EF Core 和泛型從資料庫中獲取物件的服務實作一些基類。考慮以下類:
/// <summary>
/// Base entity getter service
/// </summary>
/// <typeparam name="TEntity">The database entity type</typeparam>
/// <typeparam name="TPK">The primary key type for example: int</typeparam>
class Service<TEntity, TPK>{
protected Func<TEntity, TPK, bool> pkFinder;
public Service(string pkname) {
var entityExpr = Expression.Parameter(typeof(TEntity), "instance");
var propertyExpr = Expression.Property(entityExpr, pkname);
var pkExpr = Expression.Parameter(typeof(TPK), "value");
var eqExpr = Expression.Equal(propertyExpr, pkExpr);
pkFinder = Expression.Lambda<Func<TEntity, TPK, bool>>(eqExpr, entityExpr, pkExpr).Compile();
}
public TEntity Get(TPK pk){
return ctx.Set<TEntity>().Where(e=>pkFinder.Invoke(e, pk)).SingleOrDefault();
}
}
所述pkname引數是保持該物體(通常為“ID”)的主鍵的屬性的名稱
的CTX物件是EF背景關系。
上面的代碼(或與此示例非常相似的代碼為清晰起見而過度簡化)失敗,物體框架無法轉換運算式。
到目前為止唯一有效的是在每個派生類中為具有實際非泛型型別的 .Where 子句實作覆寫,但是我想避免一遍又一遍地重新實作相同的代碼。
另一個想法是讓物體類從某個基類派生,但由于它們是自動生成的,這可能會有問題。
任何新想法將不勝感激。
uj5u.com熱心網友回復:
您已經獲得了生成運算式以根據已知值檢查 ID 的所有代碼。只需將其放入您的Get方法中,并使用Expression.Constant帶有pk值的 ,而不是Expression.Parameter用于您的pkExpr.
我還沒有測驗過,但這樣的事情應該可以作業:
private readonly string pkname;
public Service(string pkname) {
this.pkname = pkname;
}
public TEntity Get(TPK pk){
var entityExpr = Expression.Parameter(typeof(TEntity), "instance");
var propertyExpr = Expression.Property(entityExpr, pkname);
var pkExpr = Expression.Constant(pk, typeof(TPK));
var eqExpr = Expression.Equal(propertyExpr, pkExpr);
var pkFinder = Expression.Lambda<Func<TEntity, bool>>(eqExpr, entityExpr);
return ctx.Set<TEntity>().Where(pkFinder).SingleOrDefault();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/380051.html
下一篇:無法將“System.Collections.Generic.List”型別的物件轉換為“System.Collections.Generic.ICollection”
