【发布时间】:2018-02-26 23:20:41
【问题描述】:
我正在使用实体框架,并准备重做一个当前使用 EF->BDO->DTO->client 的项目,并在此过程中为每个类进行手动转换。
我遇到了 AutoMapper,并认为这将是一个整体上更好的解决方案。我在映射 CustomerEF -> CustomerDto、OfficeEF -> OfficeDto 等时没有遇到任何问题,但我现在正在研究一个更复杂的类,并且努力让一切都到位。
我觉得我很接近,并且必须反过来发生一些事情,但我无法确定我错过了什么。
public class CaseDto
{
public int CaseId { get; set; }
public string CaseReason { get; set; }
public CustomersDto _customer { get; set; }
public OfficeDto _office { get; set; }
public CaseNotesDto[] _caseNotes { get; set; }
}
public class CustomersDto
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
public class OfficeDto
{
public int OfficeId { get; set; }
public string OfficeName { get; set; }
}
public class CaseNotesDto
{
public int CaseNotesId { get; set; }
public int CaseId { get; set; }
public string CaseNote { get; set; }
}
// EF objects
public class CaseEF
{
public int CaseId { get; set; }
public string CaseReason { get; set; }
public int CustomerId { get; set; }
public int OfficeId { get; set; }
}
public class CustomerEF
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
public class OfficeEF
{
public int OfficeId { get; set; }
public string OfficeName { get; set; }
}
public class CaseNotesEF
{
public int CaseNotesId { get; set; }
public int CaseId { get; set; }
public string CaseNote { get; set; }
}
// execution classes
public class CaseFramework
{
// set 'ef' variables
private readonly OfficeEF _officeEf = new OfficeEF { OfficeId = 1, OfficeName = "Washington" };
private readonly CustomerEF _customerEf = new CustomerEF { CustomerId = 1, CustomerName = "Blips and Chitz" };
private readonly CaseNotesEF[] _caseNotesEf =
{
new CaseNotesEF {CaseNotesId = 1, CaseNote = "Case 1", CaseId = 1000},
new CaseNotesEF {CaseNotesId = 2, CaseNote = "Case 2", CaseId = 1000}
};
private readonly CaseEF _case =
new CaseEF { CaseId = 1000, CaseReason = "Roy is back!", CustomerId = 1, OfficeId = 1 };
public CaseDto GetCase(int caseId)
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<OfficeEF, OfficeDto>();
cfg.CreateMap<CustomerEF, CustomersDto>();
cfg.CreateMap<CaseNotesEF, CaseNotesDto>();
cfg.CreateMap<CaseEF, CaseDto>()
.ForMember(dest => dest._customer, opt => opt.MapFrom(src => src.CustomerId))
.ForMember(dest => dest._office, opt => opt.MapFrom(src => src.OfficeId))
.ForMember(dest => dest._caseNotes,
opt => opt.MapFrom(src => _caseNotesEf.Where(x => x.CaseId == caseId)));
});
Mapper.AssertConfigurationIsValid();
var source = new CaseEF { CaseId = caseId };
var destination = Mapper.Map<CaseEF, CaseDto>(source);
return destination;
}
}
为了运行这个我正在做的事情:
var b = new CaseFramework();
var result = b.GetCase(1000);
结果是填充 CaseId(手动设置)和 CaseNotesDto,但仅此而已。
在 Mapper.Initialize 部分中拥有前 3 个 cfg.CreateMap 项无论它们是否存在都没有区别。
提前感谢您的任何指导。
【问题讨论】:
-
一个更好的整体解决方案是使用适合您所有层的 T4 生成的 POCO 类,而不是每个层。 Canonical schema/model 消除了所有繁琐且耗时的数据转换;消除了数据保真度丢失的风险并大大减少了维护
-
基本上,你不能从一个 id 映射到一个类。您的案例实体 (CaseEF) 下方应有 navigation properties (classes) 用于客户、办公室和案例说明。带有 EF 的 automapper 的美妙之处在于您可以一步获取它们并一步映射它们(不需要
.ForMember(),除非您正在做一些不正常的事情)。 -
完成后,它可能看起来像
var caseDTO = context.Cases.Include(c => c.Customer).Include(c => c.Office).Include(c => c.Notes).Project().To<CaseDTO>().ToList();
标签: c# entity-framework-6 automapper