gpt4 book ai didi

c# - AutoMapper 和 Entity Framework Include 与无跟踪的循环关系

转载 作者:行者123 更新时间:2023-11-30 23:02:43 27 4
gpt4 key购买 nike

使用 Entity Framework 6,我尝试使用 .AsNoTracking() 从数据库中急切地加载我的 Caller 模型,但是当我遇到问题时尝试使用 AutoMapper 6 将这些模型映射到它们的 ViewModel。

Caller有一个Address,是多对一的关系(caller's可以有一个地址,address可以有多个caller)。

这是(简化的)模型类(ViewModels 几乎相同)

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

抛出的异常是

Error Mapping Types ... Caller.Address -> CallerViewModel.Address ... When an object is returned with a NoTracking merge option, Load can only be called when the EntityCollection or EntityReference does not contain objects.

当我删除 .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<strike>.MapFrom(m => m.Callers)</strike>.Ignore())
.ForMember(vm => vm.City, map => map.MapFrom(m => m.City))
.ReverseMap();

我对我的 Caller -> CallerViewModel map 上的另一个属性 CallDetailViewModels 也做了同样的事情


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<strike>.MapFrom(m => m.CallDetails)</strike>.Ignore())

我看到这和 Address 之间的相似之处在于 CallerAddress 的父对象,而 CallDetailCaller

的父对象

这两个父类都是各自模型类中的导航属性:

Caller -> public virtual ICollection<CallDetail> CallDetails { get; set; }
Address -> public virtual ICollection<Caller> Callers { get; set; }

也许这可能会给其他人一个有用的标记,让他们知道他们可能在哪里遇到这个问题。

注意:我的 CallDetailCaller 是多对多的关系,所以它也有一个导航属性 调用者,我不会在我的 CallDetail map 中忽略它。

最佳答案

我不完全确定为什么会这样,但我猜问题是当您使用 .AsNoTracking()Address -> Callers 之间发生了一些事情在上下文中,因此不再有映射 ICollection<Caller> 的方法及其 View 模型。

既然你提到你只想要 Caller -> Address你应该试试这张 map :

// 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();

关于c# - AutoMapper 和 Entity Framework Include 与无跟踪的循环关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50338017/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com