AutoMapper 随机丢失映射信息

AutoMapper randomly lose mapping informations

我们有一个解决方案,WCF 服务使用 EF 6 从数据库获取数据。通过 IoC 容器注入存储库 DLL。在此 DLL 中,您可以找到实体、上下文、AutoMapper 配置文件等。

这是 SubscriberProfile 的示例:

public class SubscriberProfile : Profile
    {
        protected override void Configure()
        {
            MapDbToDto();
        }

        private static void MapDbToDto()
        {
            Mapper.CreateMap<SubscriberDb, SubscriberDto>()
                  .ForMember(x => x.FieldA, opt => opt.MapFrom(x => x.Filed123.Valeur))
                  .ForMember(x => x.Contact, opt => opt.Condition(src => !Helpers.IsAllDefault(src.Contact)))
                  .ForMember(x => x.Conjoint, opt => opt.Condition(src => !Helpers.IsAllDefault(src.Conjoint)));
            Mapper.CreateMap<AnotherDb, AnotherDto>();
            Mapper.CreateMap<ContactDb, ContactDto>();
        }
    }

以及添加配置文件的配置文件:

    public static class AutoMapperRepositoryConfiguration
    {  
        //Create mapings only once
        public static void Configure()
        {
            if (Mapper.GetAllTypeMaps().Any())
                return;

            Mapper.Configuration.DisableConstructorMapping();

            Mapper.AddProfile(new ConventionProfile());
            Mapper.AddProfile(new SubscriberProfile());
            Mapper.AddProfile(new BeneficiaryProfile());
        }
}

并且在每个 repo 构造函数中调用 Configure 方法,因此它获取映射:

public SubscriberReadRepository(PlansContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            AutoMapperRepositoryConfiguration.Configure();
            _context = context;
        }

一切正常,几乎所有时间。在服务器上,有时不知从何而来,我们会收到臭名昭著的“缺少类型映射配置或不支持的映射”错误:

System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: Missing type map configuration or unsupported mapping.

Mapping types:
SubscriberDb -> SubscriberDto
MyRepo.SouscripteurDb -> MyRepo.SubscriberDto

Destination path:
SubscriberDto

Source value:
System.Data.Entity.DynamicProxies.SubscriberDb_0498438FE3D70326924850E4199183EC0EB2AC8DF509202F8CB4EF2D02D9E835 (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.

Mapping types:
SubscriberDb -> SubscriberDto
MyRepo.SouscripteurDb -> MyRepo.SouscripteurDto

Destination path:
SubscriberDto

Source value:
System.Data.Entity.DynamicProxies.SubscriberDb_0498438FE3D70326924850E4199183EC0EB2AC8DF509202F8CB4EF2D02D9E835
   at MyRepo.SubscriberReadRepository.Get(Int32 idSouscripteur) in e:\BuildAgent\workdd90bc72a81e0e3\Sources\MyRepo\SubscriberReadRepository.cs:line 59
   at MyRepo.SubscriberReadServices.Get(Int32 id) in e:\BuildAgent5\workdd90bc72a81e0e3\Sources\MyRepo\SubscriberReadServices.cs:line 33
   at WCF.Services.SubscriberServices.Get(Int32 id) in e:\BuildAgen...).

一旦我们收到错误,none 的后续调用将起作用,但它们都会因相同的错误而崩溃。然后我们转到 IIS 并重新启动 WCF 服务,一切恢复正常。它可以毫无问题地工作几天,然后无缘无故地再次发生。我们的 DBA 确保没有对数据库进行任何修改。有人有想法吗?我在 Google 上到处检查,但找不到像我们这样随机的东西。我在这里看到了一个 post,其中 Jimmy Bogard 谈到在 "Mapper.CreateMap" 上调用 "base.CreateMap" 而不是,但还没有尝试过,因为我们甚至不知道为什么会出现这个错误。

您调用了错误的 CreateMap 方法。在您的配置文件中调用基本 CreateMap 方法 class:

public class SubscriberProfile : Profile
{
    protected override void Configure()
    {
        MapDbToDto();
    }

    private static void MapDbToDto()
    {
        CreateMap<SubscriberDb, SubscriberDto>()
              .ForMember(x => x.FieldA, opt => opt.MapFrom(x => x.Filed123.Valeur))
              .ForMember(x => x.Contact, opt => opt.Condition(src => !Helpers.IsAllDefault(src.Contact)))
              .ForMember(x => x.Conjoint, opt => opt.Condition(src => !Helpers.IsAllDefault(src.Conjoint)));
        CreateMap<AnotherDb, AnotherDto>();
        CreateMap<ContactDb, ContactDto>();
    }
}

你的初始化会更好地使用 Initialize:

public static class AutoMapperRepositoryConfiguration
{  
    //Create mapings only once
    public static void Configure()
    {
        if (Mapper.GetAllTypeMaps().Any())
            return;

        Mapper.Initialize(cfg => {
            cfg.DisableConstructorMapping();

            cfg.AddProfile(new ConventionProfile());
            cfg.AddProfile(new SubscriberProfile());
            cfg.AddProfile(new BeneficiaryProfile());
        });
    }
}