【问题标题】:Inconsistent Mapping Behavior in AutoMapper 3AutoMapper 3 中的映射行为不一致
【发布时间】: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 语句?我可能是错的,但看起来您在执行映射之前运行它们。但是它们应该在应用程序启动时运行一次。现在,哪个先出现只是巧合。
  • 我通常在执行它们之前运行它们。我在以前的应用程序中这样做过,我从来没有遇到过问题,但我可以将它们放在一个中心位置。
  • 我很确定它会解决您的问题。在EventEventViewModel 之间会有一个映射,所以你必须选择它是哪一个(或组合映射)。
  • 你是对的!无论首先创建什么地图,都将在应用程序的生命周期内使用。我需要你把这个写下来作为答案。

标签: c# asp.net-mvc entity-framework automapper automapper-3


【解决方案1】:

问题是您在使用映射之前创建(配置)映射。现在,哪个映射首先创建并因此占上风,这是一个巧合。

AutoMapper documentation 说:

如果您使用的是静态 Mapper 方法,则每个 AppDomain 只应进行一次配置。这意味着放置配置代码的最佳位置是在应用程序启动中,例如用于 ASP.NET 应用程序的 Global.asax 文件。

这意味着您在EventEventViewModel 之间只有一个映射,这可能应该是您现在拥有的两者的组合。

顺便说一句,你可以通过DynamicMap执行偶尔的映射。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 2020-05-19
    • 2022-11-27
    • 2014-12-02
    • 2018-11-15
    相关资源
    最近更新 更多