Satyajit
Satyajit

Reputation: 2071

Extending a Select.... to accommodate more fields as extension using EF

I have a class:

public class Employee
{
  public int Id { get; set; }
  public string Name { get; set; }
  public int Salary { get; set; }

  public string Address {get;set;}
}

And query using Entity Framework is:

var selectedEmployee = entities.Employees
                             .Where(e=>e.Salary>10000)
                             .Select(emp => new EmpDTO
                                  {
                                      Id = emp.Id,
                                      Name = emp.Name,
                                      Salary = emp.Salary
                                  });

My question is: I want to allow extending this query without rewriting the base query. It should allow adding a new field in the .Select(.....) by extending the above query.

Without rewriting the complete query:

var selectedEmployee = entities.Employees
                                 .Where(e=>e.Salary>10000)
                                 .Select(emp => new EmpDTO
                                      {
                                          Id = emp.Id,
                                          Name = emp.Name,
                                          Salary = emp.Salary,

                                          Address = emp.Address

                                      });

How can I do that?

Thanks

Upvotes: 0

Views: 130

Answers (1)

Slava Utesinov
Slava Utesinov

Reputation: 13488

If I understand, you can try this:

public IQuerable<EmpDTO> GetEmployee(Func<Employee, EmpDTO> projection = null)
{
    if(projection == null)
        projection = emp => new EmpDTO {
                                  Id = emp.Id,
                                  Name = emp.Name,
                                  Salary = emp.Salary,    
                                };
    return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}

Implementation:

var query = classInstance.GetEmployee();
//or
query = classInstance.GetEmployee(emp => new EmpDTO {
                                          Id = emp.Id,
                                          Name = emp.Name,
                                          Salary = emp.Salary,    
                                          Address = emp.Address
                                      });

If you always want to get some set of fields, like Id, Name and Salary and sometimes take additional fields(and specify only their as method arguments), you should to take all fields from DB and only then filter them depends on your condition - it is bad practice to do SELECT *, so you should get default set of fields or specify all desired fields mannualy.

Solution with SELECT *:

public List<EmpDTO> GetEmployee(Func<Employee, EmpDTO> projection)
{
    var query = entities.Employees.Where(e => e.Salary > 10000).ToList().Select(x => {
         var item = projection == null ? new EmpDTO() : projection(x);
         item.Id = x.Id;
         item.Name = x.Name;
         item.Salary = x.Salary;
         return item;
     }).ToList();
}

At this case return value is List<T> not IQuerable<T>;

Implementation:

var items = classInstance.GetEmployee(emp => new EmpDTO { Address = emp.Address });
//items also will contain fields: Id, Name and Salary by default

Upvotes: 1

Related Questions