My colleague is trying to fetch only needed properties as best practice for avoid unnecessary workload on database side as below.
public async Task<IEnumerable<Product>> GetProducts(List<int> ids)
{
var items = await _context.Products.Where(u => ids.Contains(u.Id))
.Select(u => new { u.Id, u.Name, u.Published })
.ToListAsync();
return items.Select(u => new Product{ Id = u.Id, Name = u.Name,Published = u.Published });
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public bool Published { get; set; }
public string MetaTitle { get; set; }
public string MetaKeywords { get; set; }
public string Sku { get; set; }
public decimal Price { get; set; }
public decimal Cost { get; set; }
public DateTime CreatedAt { get; set; }
///...And other properties goes here
}
As you have seen, there are only 3 properties fetched from database despite product has many properties.
IMO fetching all properties is not really has important workload. I would only do this in the case when there is performance issue on the query. i have been pointed that it is not possible to know what exactly returned from method without reading implementation detail. Not only that, you can't use exactly same method name when you need another method which has exactly same method sign but fetching different properties. For example
public async Task<IEnumerable<Product>> GetProducts(List<int> ids)
{
//logic goes here
return items.Select(u => new Product{ Id = u.Id, Name = u.Name,Published = u.Published });
}
public async Task<IEnumerable<Product>> GetProducts(List<int> ids)
{
//logic goes here
return items.Select(u => new Product{ Id = u.Id, Name = u.Name,Cost = u.Cost, Sku = u.Sku });
}
Code is not going to be compiled because there are exactly same 2 methods and one of them should differentiate it's name. I am sure that it is really hard give meaningful names for such cases.
His arguments was returning specific Types(DTO) would cause a lot of types in the project.
It is actually a lot of types are not only issue. You can not use exactly same method name as well and it is very hard to give meaningful names for types and method names.
My solution to this problem, don't put this logic in a method. Inline query wherever it is used. Already there is no re-usability of the query and also query really doesn't contains any kind of logic which deserves to be reused in other places. But according to his idea, queries shouldn't not executed outside of service methods because strict layering rules.
Shortly what is your idea about returning partially filled entity from method ? Secondly what if we want to fetch only requested properties so what is best way to do that ?
I know you will say use DTO but trying to design everything this way going to make everything harder so in my opinion it should to be only used in the case of performance related issue but still inlining query fix all of these issues but some people have strict layering rules without pragmatic reasons.
I would like to hear your opinions.
ProductInfo
that would only contains desired properties...