将 AutoMapper 与实体框架一起使用时出现异常

Posted

技术标签:

【中文标题】将 AutoMapper 与实体框架一起使用时出现异常【英文标题】:Exception using AutoMapper with Entity Framework 【发布时间】:2012-11-17 05:49:25 【问题描述】:

我正在尝试使用实体框架将 Automapper 包含到项目中,这是我的 DTO 类:

public class FunctionDto

    public int Id  get; set; 
    public string Name  get; set; 
    public DateTime? StartDate  get; set; 
    public DateTime? EndDate  get; set; 
    public string Comment  get; set; 
    public DateTime? ExaminationDate  get; set; 
    public string Place  get; set; 

域类代码优先:

public class Function

    public int Id  get; set; 
    public string Name  get; set; 
    public DateTime? StartDate  get; set; 
    public DateTime? EndDate  get; set; 
    public string Comment  get; set; 
    public DateTime? ExaminationDate  get; set; 
    public string Place  get; set; 

    public virtual List<Employee> Employees  get; set; 

自动映射器配置:

public static class AutoMapperConfiguration

    public static void Configure()
    
        Mapper.Initialize(config => config.AddProfile<FunctionProfile>());
    


public class FunctionProfile : Profile

    protected override void Configure()
    
        CreateMap<Function, FunctionDto>()
        .ForMember(dto => dto.Id, opt => opt.MapFrom(src => src.Id))
        .ForMember(dto => dto.Name, opt => opt.MapFrom(src => src.Name))
        .ForMember(dto => dto.Comment, opt => opt.MapFrom(src => src.Comment))
        .ForMember(dto => dto.StartDate, opt => opt.MapFrom(src => src.StartDate))
        .ForMember(dto => dto.EndDate, opt => opt.MapFrom(src => src.EndDate))
        .ForMember(dto => dto.ExaminationDate, opt => opt.MapFrom(src => src.ExaminationDate))
        .ForMember(dto => dto.Place, opt => opt.MapFrom(src => src.Place));
       

然后在WebApi中使用:

var functionDtos = functions
            .AsQueryable()
            .OrderBy(sort)
            .Skip(start)
            .Take(count)
            .ToList()
            .Select(Mapper.Map<FunctionDto>);

当然我已经在全球注册了:

 AutoMapperConfiguration.Configure();

但我得到了例外:

缺少类型映射配置或不支持的映射

上面的代码有什么问题?

【问题讨论】:

不是一个答案(还),但这样做就足够了CreateMap&lt;Function, FunctionDto&gt;();,因为所有成员都有相同的名字。如果将初始化语句放在 linq 查询之前会发生什么? (仅供尝试) @GertArnold:Dto 没有员工,只是很明确。我试过functions.Select(Mapper.Map&lt;FunctionDto&gt;) 仍然得到同样的错误。由于延迟加载,这里的函数也是代理类 我使用 AutoMapper 2.1 (Nuget),它从代理映射到 dto 的 v.v.我知道代理可能会导致问题(在 SO 这里有关于它的问题),但在我使用的版本中似乎没问题。 【参考方案1】:

请您确认functions是什么,如下所示:

MapperConfiguration.cs

namespace ***.Function

    using AutoMapper;

    public class MyProfile : Profile
    
        protected override void Configure()
        
            CreateMap<Function, FunctionDto>();
        
    

MappingTests.cs

[TestFixture]
public class MappingTests

    [Test]
    public void AutoMapper_Configuration_IsValid()
    
        Mapper.Initialize(m => m.AddProfile<MyProfile>());
        Mapper.AssertConfigurationIsValid();
    

    [Test]
    public void AutoMapper_Mapping_IsValid()
    
        Mapper.Initialize(m => m.AddProfile<MyProfile>());
        Mapper.AssertConfigurationIsValid();

        var functions = new List<Function>
            
                new Function
                    
                        Comment = "Stack Overflow Rocks",
                        EndDate = new DateTime(2012, 01, 01),
                        ExaminationDate = new DateTime(2012, 02, 02),
                        Id = 1,
                        Name = "Number 1",
                        Place = "Here, there and everywhere",
                        StartDate = new DateTime(2012, 03, 03)
                    ,
                new Function
                    
                        Comment = "As do I",
                        EndDate = new DateTime(2013, 01, 01),
                        ExaminationDate = new DateTime(2013, 02, 02),
                        Id = 2,
                        Name = "Number 2",
                        Place = "Nowhere",
                        StartDate = new DateTime(2013, 03, 03)
                    
            ;

        var functionDtos = functions
            .AsQueryable()
            .OrderBy(x => x.Id)
            .Skip(1)
            .Take(1)
            .ToList()
            .Select(Mapper.Map<FunctionDto>);

        Assert.That(functionDtos, Is.Not.Null);
        Assert.That(functionDtos.Count(), Is.EqualTo(1));
        Assert.That(functionDtos.First().Id, Is.EqualTo(2));
    

【讨论】:

【参考方案2】:

试试这个Configure()方法,

注意:如果Function, FunctionDto 具有相同名称的属性,则不需要映射。 AutoMapper 会负责映射。

protected override void Configure()

    CreateMap<Function, FunctionDto>().IgnoreAllNonExisting();

--

    public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    
        var sourceType = typeof(TSource);
        var destinationType = typeof(TDestination);
        var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
        foreach (var property in existingMaps.GetUnmappedPropertyNames())
        
            expression.ForMember(property, opt => opt.Ignore());
        
        return expression;
    

【讨论】:

以上是关于将 AutoMapper 与实体框架一起使用时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

实体框架与集合对象,使用 Automapper,更新时异常

使用 Automapper,将 DTO 映射回实体框架,包括引用的实体

内存泄漏实体框架

首先将可更新视图与实体框架代码一起使用

模块解析失败:将 React on Rails 与 Antd 一起使用时出现意外字符“@”。

使用 automapper 更新实体框架实体