简体   繁体   中英

Using LINQ to Entities extension methods for more than one entity type

I have the following extension methods:

public static IQueryable<Employee> WhereStatus(this IQueryable<Employee> queryable, string status)
{
    var result = queryable
        .Where(e => e.EmployeeStatus.Where(s => s.StatusEndDate == null).Select(s => s.Status)
        .FirstOrDefault() == status);

    return result;
}

public static IQueryable<Employee> WhereCostCenter(this IQueryable<Employee> queryable, int costCenterID)
{
    var result = queryable
        .Where(e => e.CostCenterID ==  costCenterID);
    return result;
}

I need these extension methods almost in every single LINQ query to filter the query to certain employees depending on few parameters (for example: status, cost center, gender...etc). Right now I am using it like this:

using (DB db = new DB())
{
      var emps = from em in db.Employees
                 .WhereStatus("Active")
                 .WhereCostCenter(112)
                 select em.EmpID;

      var courses = from cr in db.Courses
                    where c.Contains(cr.EmpID)
                    select cr;

      // now I have the filtered list of the courses I want
      .....
}

Question: Is that the best practice? or is there a way to make the extension method works with all entity types I have since all entities have an EmpID? something like:

var courses = from em in db.Courses
              .WhereStatus("Active")    // use the extension methods directly here as well
              .WhereCostCenter(112)
              select cr;

The problem is that not all of the entities will have the properties necessary to use all of the extension methods. What you can do is create subsets of the properties, and place them into interfaces.

Example:

public interface IHaveCostCenterID
{
    public int CostCenterID {get; set;}
}

public partial class Employee : IHaveCostCenterID
{
}

public partial class Department : IHaveCostCenterID
{
}

public static IQueryable<IHaveCostCenterID> WhereCostCenter(this IQueryable<IHaveCostCenterID> queryable, int costCenterID)
{
    var result = queryable
        .Where(e => e.CostCenterID ==  costCenterID);
    return result;
}

Another way:

public static class Extension
{
    public static IQueryable<TEntity> WhereCostCenter<TEntity>(
        this IQueryable<TEntity> queryable, int costCenterID)
        where TEntity : IHaveCostCenterID
    {
        var result =
            queryable.Where(e => e.CostCenterID == costCenterID);
        return result;
    }
}

public interface IHaveCostCenterID
{
    int CostCenterID { get; set; }
}

public partial class Employee : IHaveCostCenterID
{
    public int CostCenterID { get; set; }
}

public partial class Department : IHaveCostCenterID
{
    public int CostCenterID { get; set; }
}

This can be a solution to use of generic methods to extract common code, and not just for LINQ. You can do this whenever you have two (or more) pieces of code which are identical except that they happen to use different classes. Extract the common part into interfaces, and have the generic method use an interface constraint.

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