Reputation: 2071
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
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
andSalary
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>
notIQuerable<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