AutoMapper 3在MVC 5的某些时候将实体框架中的相关实体映射到视图模型时遇到了问题。我使用EF 6.1.1来获取数据,并且轻量级存储库层来集中查询。这个问题似乎只发生在根实体下的实体的映射属性,但问题是间歇性的。在重建解决方案之后,我发现行为重新开始工作,重建解决方案后行为中断,而不更改发生问题的代码。
我已经在调试器和SQL分析器中对此进行了测试,即使数据未显示在前端,我也可以在SQL分析器中看到实体框架正在加载相关的表。
问题的示例映射
在从存储库层查询数据后,此代码在MVC控制器中执行。然后将视图模型传递给视图进行渲染。
Mapper.CreateMap<Event, EventViewModel>()
.ForMember(e => e.EventTitleId, opt => opt.MapFrom(x => x.EventTitleType.EventTitleId));
EventViewModel model = Mapper.Map<Event, EventViewModel>(eventItem);
//Fix Up I had to implement to ensure the data gets into the property
model.EventTitleId = eventItem.EventTitleType.EventTitleId;
使用问题映射的另一个示例
在不同控制器操作下的相同基本执行路径,同样的问题。
Mapper.CreateMap<Event, EventViewModel>()
.ForMember(l => l.EventTitle, opt => opt.MapFrom(x => x.EventTitleType.EventTitle.Title))
.ForMember(l => l.EventType, opt => opt.MapFrom(x => x.EventTitleType.LkEventType.Title))
.ForMember(l => l.LocationName, opt => opt.MapFrom(x => x.LkLocation.LocationName));
IEnumerable<EventViewModel> eventList = Mapper.Map<IEnumerable<Event>, IEnumerable<EventViewModel>>(events);
同样,有时这三个属性会获得数据,有时它们不会。
数据模型
这就是数据模型的样子。
存储库
存储库层包装了实体框架调用,但它并没有抽象出实体框架实体及其带来的问题和好处。项目中的所有存储库都继承了IRepository,我使用该层来集中查询和业务逻辑。
using System.Collections.Generic;
namespace Tools.Repository
{
/// <summary>
/// Generic Repository Interface
/// </summary>
/// <typeparam name="TClass">Class that the Repository is implemented for.</typeparam>
public interface IRepository<TClass>
where TClass : class
{
void SaveChanges();
TClass Find(params object[] keyValues);
IEnumerable<TClass> GetAll();
TClass Add(TClass itemToAdd);
TClass Update(TClass itemToUpdate);
TClass Remove(TClass itemToDelete);
}
}
摘要
我不相信这是一个实体框架延迟加载问题,并且在迫使EF急切加载数据之后,问题仍然存在。实体在映射之前具有调试器中的值,但有时仅将值映射到视图模型。最令人沮丧的是,这个问题似乎并不是由我对视图模型所做的任何改变造成的。
什么可能导致这种不一致的行为?我对AutoMapper 3.2.1和3.1.1都有这个问题。
答案 0 :(得分:2)
问题是您在使用映射之前创建(配置)映射。现在,首先创建映射并因此占优势是巧合。
如果您使用静态Mapper方法,则每个AppDomain只应进行一次配置。这意味着放置配置代码的最佳位置是应用程序启动,例如ASP.NET应用程序的Global.asax文件。
这意味着Event
和EventViewModel
之间只有一个映射,可能应该是您现在拥有的两个映射。
顺便说一下,您可以DynamicMap
执行偶尔的映射。