c# #asp.net #entity-framework-core #automapper
#c# #asp.net #entity-framework-core #automapper
Вопрос:
Я работаю над отображением нескольких объектов базы данных для инструмента отчетности.
На данный момент существует несколько вычисляемых свойств в зависимости от свойств навигации для их загрузки. Они были привязаны через AutoMapper, чтобы упростить процесс.
public class Customer
{
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Foo> Foos { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
}
public class CustomerDto
{
public long Id { get; set; }
public string Name { get; set; }
public long TotalNumberOfFoos { get; set; }
public long NumberOfBarsWithCondition { get; set; }
}
public class CustomerProfile : Profile
{
public CustomerProfile()
{
CreateMap<Customer, CustomerDto>()
.ForMember(d => d.TotalNumberOfFoos, p => p.MapFrom(c => c.Foos.Count))
.ForMember(d => d.NumberOfBarsWithCondition, p => p.MapFrom(c => c.Bars.Where(b => b.BarProperty == "something").Count()));
}
}
public class CustomerController : Controller
{
public async Task<List<CustomerDto>> CustomersByName(string name)
{
using (var db = new MyDbContext())
{
return await db.Customers
.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider)
.Where(c => c.Name == name).ToListAsync();
}
}
}
Конечно, запросы для извлечения этих свойств могут стать довольно дорогостоящими по мере увеличения размера базы данных, и они не всегда нужны в итоговом отчете.
Идея состоит в том, чтобы у пользователя была возможность выбрать, хотят ли они, чтобы они были включены или нет в окончательный отчет, но я не нашел способа сделать сопоставление необязательным во время запроса.
Есть ли способ сделать это автоматически, или я вынужден материализовать список и самостоятельно запрашивать эти свойства отдельно, теряя преимущество наличия вычисляемых свойств из базы данных?
Комментарии:
1. Я предполагаю, что вы ищете явное расширение AutoMapper. Что, вероятно, следует называть «явным включением свойств» (не следует смешивать с ядром EF
Include
, которое предназначено только для навигации).2. @IvanStoev Это именно то, что мне было нужно! Я протестировал его, и он творит чудеса. Я был бы рад отметить это как ответ, если вы опубликуете его как один.
Ответ №1:
Что вам нужно, так это использовать так называемую функцию явного расширения AutoMapper. Который, вероятно, следует называть «явным включением свойств» (не следует смешивать с ядром EF Include
, которое предназначено только для навигации), поскольку он работает для любого целевого свойства, и то, что он делает, скорее включает его автоматически в сгенерированную проекцию ( Select
), включает его только при явном выборе.
Итак, сначала вам нужно настроить такие свойства, как ExplicitExpansion()
, например
CreateMap<Customer, CustomerDto>()
.ForMember(d => d.TotalNumberOfFoos, p =>
{
p.MapFrom(c => c.Foos.Count);
p.ExplicitExpansion();
})
.ForMember(d => d.NumberOfBarsWithCondition, p =>
{
p.MapFrom(c => c.Bars.Where(b => b.BarProperty == "something").Count());
p.ExplicitExpansion();
});
Теперь по умолчанию они не будут заполнены. Используйте дополнительные аргументы ProjectTo
, чтобы передать, какие из них вы хотите «развернуть» (включить), например
.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider, e => e.TotalNumberOfFoos)