2014-01-29 29 views
4

我有各種類型的EF實體,它們都有一個名爲「Employee」的導航屬性。生成報告時,用戶可以根據不同的員工特徵(成本中心,性別等)篩選報告。Linq-EF查詢的通用過濾方法

目前我單獨濾波過程中每個查詢,例如:

var courses = context.Courses 
       .Where(c => c.Employee.CostCenterID == ccID 
        && c.Employee.Rank == rankID 
        .... 
        ) 
        .ToList(); 

真正的濾波代碼爲更多的時間,但這個只是一個暗示。無論如何,有沒有辦法創建一個通用的方法來過濾員工的結果?我將提供給此過濾器方法的所有實體將具有Employee導航屬性。我會簡單地提供一個IQueryable<entity>ObjectSet<entity>,然後得到過濾IQueryable<entity>ObjectSet<entity>

如何做到這一點?

回答

1

我只是想通了!因爲我們不能在泛型方法添加約束來檢查某個屬性,我設法用一個接口來做到這一點:

public interface IFilterable 
{ 
    Employee Employee 
    { 
     get; 
     set; 
    } 
} 

然後,我添加了部分類繼承的不同實體上一界面具有Employee導航屬性,例如:

public partial class Course: IFilterable 
{ 
} 

然後創建以下通用方法:

public static IQueryable<T> Filter<T>(this IQueryable<T> source, SearchCriteria sc) 
    where T : class, IFilterable 
{ 
    var filtered = source.Where(e => e.Employee.CostCenterID == sc.CostCenterID 
     && e.Employee.Gender == sc.Gender); 

    return filtered; 
} 

然後只需我可以使用它這樣就繼承IFilterable任何類:

var list = context.Courses.Filter(sc).ToList(); 

注:SearchCriteria只是一個簡單的類,用於保存不同的員工屬性。

請如果有更好的方法做到這一點,張貼它。

+0

我想你應該張貼此代碼問題上http://codereview.stackexchange.com/代替回答你自己的問題,並要求更好的解決方案 –

+0

@SergeyBerezovskiy在問這個問題時,我不知道答案,在發佈問題後我想出了答案。所以我不喜歡給教程什麼的。你知道那些答案剛剛出現在你腦海中的時刻... –

+1

@SergeyBerezovskiy無論如何,謝謝。我也在代碼評論中發佈。 –

1

如果你想避免實現一個接口:

public Expression<Func<TEntity, bool>> EmployeeFilterDelegateExp<TEntity>( 
    int costCenterId, 
    int rankId) 
{ 
    var parm = Expression.Parameter(typeof(TEntity), "entity"); 
    var employeeProperty = Expression.Property(parm, "Employee"); 

    return (Expression<Func<TEntity, bool>>)Expression.Lambda(
     Expression.AndAlso(
      Expression.Equal(Expression.Property(employeeProperty, "CostCenterID"), 
       Expression.Constant(costCenterId)), 
      Expression.Equal(Expression.Property(employeeProperty, "Rank"), 
       Expression.Constant(rankId))), 
     parm); 
} 

用法:

var courses = context.Courses 
    .Where(EmployeeFilterDelegateExp<Course>(ccID, rankID)) 
    .ToList();