可选加载EF Core计算属性



我正在为一个报告工具映射几个数据库实体。

目前,有一些计算属性依赖于导航属性的加载。他们已经通过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();
}
}
}

当然,随着数据库大小的增加,检索这些属性的查询可能会变得非常昂贵,并且在最终报告中并不总是需要它们。

这个想法是为用户提供一个选项,让他们选择是否要在最终报告中包含它们,但是我还没有找到一种在查询时使映射可选的方法。

是否有自动执行此操作的方法,或者我是否被迫实现列表并单独查询这些属性,从而失去从数据库中计算属性的优势?

您需要的是利用所谓的AutoMapper Explicit扩展特性。这应该被称为"显式属性包含"。(不要与只用于导航的EF CoreInclude混在一起),因为它适用于任何目的地属性,而它所做的是将其自动包含在生成的投影中(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)

相关内容

  • 没有找到相关文章

最新更新