使用实体框架6,我尝试使用Caller
从数据库急切加载.AsNoTracking()
模型,但是当我尝试映射这些模型时,我遇到了麻烦使用AutoMapper 6到他们的ViewModels。
Caller
有Address
,这是多对一关系(来电者可以有一个地址,地址可以有多个来电)。
以下是(简化的)模型类(ViewModel几乎相同)
public class Caller
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public Address Address { get; set; }
}
public class Address
{
public Guid Id { get; set; }
public string City { get; set; }
public virtual ICollection<Caller> Callers { get; set; }
}
以下是我如何映射它们
// Address
CreateMap<Address, AddressViewModel>()
.ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
.ForMember(vm => vm.CallerViewModels, map => map.MapFrom(m => m.Callers))
.ForMember(vm => vm.City, map => map.MapFrom(m => m.City))
.ReverseMap();
// Caller
CreateMap<Caller, CallerViewModel>()
.ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
.ForMember(vm => vm.AddressViewModel, map => map.MapFrom(m => m.Address))
.ForMember(vm => vm.FirstName, map => map.MapFrom(m => m.FirstName))
.ReverseMap();
在我CallerRepository
我正在使用此功能:
public async Task<Caller> GetFullCallerAsNoTrackingAsync(Guid id)
{
return await _context.Callers
.AsNoTracking()
.Include(c => c.Address)
.FirstOrDefaultAsync(c => c.Id == id);
}
我的问题发生在这里:
// Map Caller to a CallerViewModel
Caller caller = await unitOfWork.CallerRepo.GetFullCallerAsNoTrackingAsync(Guid.Parse(callerId));
CallerViewModel callerViewModel = Mapper.Map<CallerViewModel>(caller); // Throws exception
抛出的异常说
错误映射类型... Caller.Address - &gt; CallerViewModel.Address ...当使用NoTracking合并选项返回对象时,只能在EntityCollection或EntityReference不包含对象时调用Load。
当我删除.AsNoTracking()
时,此工作正常,但出于性能原因,我试图将其保留。
我不需要知道Caller -> Address -> Callers
,我只需要Caller -> Address
关于如何实现这一目标的任何建议?
感谢FoundNil's answer我能够完成这项工作。
我将Address
地图更改为:
CreateMap<Address, AddressViewModel>()
.ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
.ForMember(vm => vm.CallerViewModels, map => map.MapFrom(m => m.Callers).Ignore())
.ForMember(vm => vm.City, map => map.MapFrom(m => m.City))
.ReverseMap();
我对CallDetailViewModels
地图上的其他媒体资源Caller -> CallerViewModel
做了同样的事情
CreateMap<Caller, CallerViewModel>()
.ForMember(vm => vm.Id, map => map.MapFrom(m => m.Id))
.ForMember(vm => vm.AddressViewModel, map => map.MapFrom(m => m.Address))
.ForMember(vm => vm.CallDetailViewModels, map => map.MapFrom(m => m.CallDetails).Ignore())
我和Address
之间的相似之处在于Caller
是Address
的父对象,而CallDetail
是Caller
的父对象< / p>
这两个父项都是各自Model类中的导航属性:
Caller -> public virtual ICollection<CallDetail> CallDetails { get; set; }
Address -> public virtual ICollection<Caller> Callers { get; set; }
也许这可能会给其他人带来一个有用的旗帜,告诉他们可能会遇到这个问题。
注意:我的CallDetail
与Caller
有多对多的关系,因此它的导航属性也为Callers
,我和# 39;我不会在我的CallDetail
地图中忽略它。
答案 0 :(得分:1)
我不完全确定它为什么会发生,但我猜这个问题是当你使用.AsNoTracking()
在上下文中Address -> Callers
之间发生某些事情时,所以不再有办法映射ICollection<Caller>
及其视图模型。
既然你提到你只想要Caller -> Address
,你应该试试这张地图:
// Address
CreateMap<Address, AddressViewModel>()
.ForMember(x => x.Callers, opt => opt.Ignore())
.ReverseMap();
// Caller
CreateMap<Caller, CallerViewModel>()
.ForMember(vm => vm.AddressViewModel, map => map.MapFrom(m => m.Address))
.ReverseMap();