【发布时间】:2014-07-01 03:56:42
【问题描述】:
我在 MVC 5 中的某些时候遇到了 AutoMapper 3 将相关实体从实体框架映射到视图模型的问题。我使用 EF 6.1.1 来获取数据,并使用轻薄的存储库层来集中查询。该问题似乎只发生在根实体下的实体的映射属性中,但问题是间歇性的。我已经看到在重建解决方案后行为再次开始工作,并且在重建解决方案后行为中断,而不更改发生问题的代码。
我已经在调试器和 SQL 分析器中对此进行了测试,即使数据没有显示在前端,我也可以在 SQL 分析器中看到 Entity Framework 正在加载相关表。
问题映射示例
在从存储库层查询数据后,此代码在 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);
同样,有时这三个属性会获取数据,有时则不会。
数据模型
这就是数据模型的样子。
存储库
存储库层封装了实体框架调用,但它并没有抽象出实体框架实体及其具有的问题和好处。项目中的所有repository都继承了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 中都遇到过这个问题。
【问题讨论】:
-
您在哪里执行
Mapper.CreateMap语句?我可能是错的,但看起来您在执行映射之前运行它们。但是它们应该在应用程序启动时运行一次。现在,哪个先出现只是巧合。 -
我通常在执行它们之前运行它们。我在以前的应用程序中这样做过,我从来没有遇到过问题,但我可以将它们放在一个中心位置。
-
我很确定它会解决您的问题。在
Event和EventViewModel之间会有一个映射,所以你必须选择它是哪一个(或组合映射)。 -
你是对的!无论首先创建什么地图,都将在应用程序的生命周期内使用。我需要你把这个写下来作为答案。
标签: c# asp.net-mvc entity-framework automapper automapper-3