После поисков вокруг это то, что я придумал. Допустим, у нас есть две контекстные сущности: пользователи и роли, к которым мы хотим присоединиться и отфильтровать
public class Roles
{
public int ID { get; set; }
}
public class Users
{
public int ID { get; set; }
}
Создать класс со всеми необходимыми выражениями. Он содержит предикаты, которые будут фильтровать данные, и ключи, которые будут использоваться для объединения таблиц
public class Expressions_BO<TObj, TBase>
{
public Expression<Func<TObj, bool>> Child_Predicate { get; set; }
public Expression<Func<TObj, decimal>> Child_Key { get; set; }
public Expression<Func<TBase, bool>> Base_Predicate { get; set; }
public Expression<Func<TBase, decimal>> Base_DS_Key { get; set; }
}
Я создаю универсальный метод, который будет объединять и фильтровать данные
public static IEnumerable<Users_With_Roles> Get_Data<TObj, TBase>(Expressions_BO<TObj, TBase> filter_Grid) where TObj : class where TBase : class
{
var roles_ctx = this.DbContext.Set<TObj>();
var users_ctx = this.DbContext.Set<TBase>();
var source = users_ctx
.Where(filter_Grid.Base_Predicate)
.Join(roles_ctx.Where(filter_Grid.Child_Predicate), filter_Grid.Base_DS_Key, filter_Grid.Child_Key,
(user, role) => new
{
});
return source;
}
Затем, если я хочу использовать это, я могу назвать это следующим образом:
static void Main(string[] args)
{
var grid_Filters = new Expressions_BO<Roles, Users>()
{
//Any predicate you want. I am just using a default always true just for this example
Child_Predicate = (x) => true,
Base_Predicate = (x) => true,
//Dealslip Base Key
Base_DS_Key = (x) => x.ID,
//Dealslip Key
Child_Key = (x) => x.ID
};
Get_Data(grid_Filters);
}
Конечно, вы можете изменить предикаты, чтобы динамически фильтровать данные, как вы хотите