Writing Computed Members with Entity Framework Core
Client side evaluation is evil, thus developers of EF Core 3 has made a good decision to forbid it. The code which could evaluates on client often leads to annoying performance issues. So I wouldn't recommend you to use computed properties in EF Core 2.* as well.
what is standardized way for computed members in Entity Framework Core
If you want to do a computation, sorting, modification, etc. as a part of your query, you should project your entity into DTO at first. In such a case, the query will be compiled into SQL query (and not evaluated on client).
For this task you can use AutoMapper library. It automatically maps properties with the same name. Other properties (computed properties) can be mapped using custom expression.
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Customer, CustomerDto>()
.ForMember(x => x.FullName, x => x.MapFrom(z => z.FirstName + " " + z.LastName))
.ForMember(x => x.AccountValue, x => x.MapFrom(z => z.Quantity * z.StockPrice));
});
var mapper = config.CreateMapper();
Then, you can use ProjectTo
extension method. ProjectTo
internally call Select
so it doesn't materialize entity. Hence, Where
statement is parsed into SQL query.
var customers = await context.Customers
.ProjectTo<CustomerDto>(mapper.ConfigurationProvider)
.Where(x => x.FullName == "full name" && x.AccountValue > 4)
.ToListAsync();
Projection of entities is often a good practice. It allows you to select just a few columns from DB and offers you other stuff that is not possible when you are returning just plain entities (e.g. sorting):
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Invoice, InvoiceDto>();
cfg.CreateMap<Customer, CustomerDto>()
.ForMember(x => x.Invoices, x => x.MapFrom(z => z.Invoices.OrderBy(x => x.Date)));
});
var mapper = config.CreateMapper();
// Customers with invoices sorted by date
var customers = await context.Customers
.ProjectTo<CustomerDto>(mapper.ConfigurationProvider)
.ToListAsync();
AutoMapper can be also used with DI. However, it is 3rd party library. If your company doesn't permit it, you can create your own mapping layer by hand. Which includes a lot of monkey work ..