简体   繁体   中英

Generic Table Join in Entity Framework

I am tryng to create a generic method that will join two tables and filter them by providing a predicate. The predicate needs to be dynamic because it will be different per user role in my application. So for example one role should see specific statuses and dates and another one might need to data for different dates.

The only similar thing I have found is the following code which just runs a provided generic predicate in a single table to filter it. So i guess i should use something similar to it

public IEnumerable<T> Get_Data<T>(Expression<Func<T, bool>> predicate) where T : class
{
     IEnumerable<T> items = null;
     items = this.DbContext.Set<T>().Where(predicate);
     return items;
}

I need to provide the tables I want to join and a combining predicate for filtering data from both tables with the type of data i want to return. Like the following maybe. I think something like the following

    public IEnumerable<Action> Get_Data<T1,T2>(
        Expression<Func<T1,T2,bool>> filterPredicate, 
        Expression<Func<T1, T2, bool>> joinPredicate) 
            where T1 : class
            where T2 : class
    {
        IEnumerable<Action> items = null;
       //join tables and filter them by using the predicate using linq
        return items;
    }

After searching around this is what I came up with. Let's say we have two context entities users and roles which we want to join and filter

    public class Roles
    {
        public int ID { get; set; }
    }

    public class Users
    {
        public int ID { get; set; }
    }

Create a class with all the required expressions. This contains the predicates which will filter the data and the keys that will be used for joining the tables

    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; }
    }

I create the generic method that will join and filter the data

    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;
    }

Then if i want to use this I can call it like this

    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);
    }

Off course you can change the predicates in order to filter the data dynamically as you wish

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM