【发布时间】:2018-02-09 07:30:23
【问题描述】:
我有 Dto 课程:
public class PackageDto
{
public MemberDto Receiver { get; set; }
public MemberDto Sender { get; set; }
public DocflowDto Docflow { get; set; }
public DocflowTypeOption DocflowTypeId { get; set; }
public string Code { get; set; }
public Guid? DocGuid { get; set; }
}
public class LightPackageDto
{
public DocflowDto Docflow { get; set; }
public DocflowTypeOption DocflowTypeId { get; set; }
public string Code { get; set; }
public Guid? DocGuid { get; set; }
}
public class MemberDto
{
public string Prop1 { get; set; }
public EntityTypeOption Prop2 { get; set; }
public string Prop3 { get; set; }
public string Prop4 { get; set; }
public string Prop5 { get; set; }
public PersonDto Director { get; set; }
public string CompanyShortName { get; set; }
public string CompanyFullName { get; set; }
public string CompanyPrefix { get; set; }
}
DocflowDto 具有 3 个简单类型属性,通过展平进行投影。 PersonDto 有 3 个简单类型属性,也可以通过扁平化来投影
映射规则:
CreateMap<Person, PersonDto>();
CreateMap<Member, MemberDto>()
.ForMember(dest => dest.Prop1, opt => opt.MapFrom(src => src.Employee.Prop1))
.ForMember(dest => dest.Prop2, opt => opt.MapFrom(src => src.Prop2))
.ForMember(dest => dest.Prop3, opt => opt.MapFrom(src => src.Employee.Prop3))
.ForMember(dest => dest.Prop4, opt => opt.MapFrom(src => src.Employee.Prop4))
.ForMember(dest => dest.Prop5, opt => opt.MapFrom(src => src.Employee.Prop5))
.ForMember(dest => dest.Director, opt => opt.MapFrom(src => src.Employee.Director))
.ForMember(dest => dest.CompanyShortName, opt => opt.MapFrom(src => src.Company.CompanyShortName))
.ForMember(dest => dest.CompanyFullName, opt => opt.MapFrom(src => src.Company.CompanyFullName))
.ForMember(dest => dest.CompanyPrefix, opt => opt.MapFrom(src => src.Company.Prefix))
;
CreateMap<Data.Models.Docflow.Package, PackageDto>()
.ForMember(dest => dest.Sender, opt => opt.MapFrom(src => src.Sender))
.ForMember(dest => dest.Receiver, opt => opt.MapFrom(src => src.Receiver))
.ForMember(dest => dest.Docflow, opt => opt.MapFrom(src => src.Docflow))
.ForMember(dest => dest.DocGuid, opt => opt.MapFrom(src => src.Files.FirstOrDefault().DocGuid))
;
CreateMap<Data.Models.Docflow.Package, LightPackageDto>()
.ForMember(dest => dest.Docflow, opt => opt.MapFrom(src => src.Docflow))
.ForMember(dest => dest.DocGuid, opt => opt.MapFrom(src => src.Files.FirstOrDefault().DocGuid));
然后测试:
//fast
var lightEntity = await _db.Packages.Where(p => p.PackageGuid == packageGuid).ProjectTo<LightPackageDto>().FirstOrDefaultAsync();
//fast (_db.GetPackage make query with all necessary includes)
var entity = await _db.GetPackage(packageGuid);
var entityDto = AutoMapper.Mapper.Map<Package, PackageDto>(entity);
//first run too slow
var result = await _db.Packages.AsNoTracking().Where(p => p.PackageGuid == packageGuid).ProjectTo<PackageDto>().FirstOrDefaultAsync();
1) 所以如果我投影到 LightPackageDto(没有成员投影)就可以了。
2) 如果我从 EF 手动返回包含包含的实体,然后我为“内存中”实体进行映射也可以
3) 如果我想要 Automapper 应用 ProjectTo 进行“选择”查询,我总是会冻结大约 2-3 秒。但是第一次冻结只出现一次。为什么?
还有其他问题。我在结果 sql select 语句中看到所有相关表的所有列。我应该只看到目标投影所需的列。为什么都在那里?
【问题讨论】:
-
尝试MyGet 构建。
-
我试过了。保存了不正确的行为((
-
感谢您的复制。我认为 AM 生成的表达式没有任何问题。但我看到很多外部连接。所以我猜在你的应用程序中,时间花在从数据库中获取东西上。
-
见this。大多数事情在第一次运行时都比较慢。 AM、EF 和 SQL Server 都会为第一次调用做额外的事情。在这种情况下,我会说它是 EF 和 SQL,但您必须对其进行分析才能确定。在您的复制中,它正在创建数据库。在现实生活中,这将是查询,因为所有这些外部连接。但你需要衡量。
-
@VitalyMosin 你找到这个问题的根源了吗?我遇到了同样的问题。第一次拨打
ProjectTo非常慢。查询本身很快,只有在我添加映射后它才会变慢。我也渴望在应用程序启动时编译我的映射,但这并没有帮助。
标签: performance entity-framework automapper