为什么Automapper.ProjectTo()抛出空引用异常?

时间:2017-04-05 19:33:21

标签: entity-framework automapper

我有一个映射:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Foo, FooDto>()
        .ForMember(dest => dest.Id,
            opt => opt.MapFrom(src => src.Id))
        .ForMember(dest => dest.Name,
            opt => opt.MapFrom(src => src.Name))
        .ForMember(dest => dest.PhoneNumber,
            opt => opt.MapFrom(src => src.PhoneNumbers.Number)) //etc.
});

我试图在单元测试中使用它来调用一些模拟的EF对象:

var ids = new List<string>()
    {
        "123";
        "456";
        "789";
    };
var data = new List<Foo>();
foreach(var id in ids)
{
    data.Add(new Foo() { Id = id });
}

this.mockContext = new Mock<entities>();
this.mockSet = new Mock<DbSet<Foo>>();
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.Provider).Returns(data.Provider);
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.Expression).Returns(data.Expression);
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.ElementType).Returns(data.ElementType);
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.GetEnumerator()).Returns(data.GetEnumerator());

当我直接查询实体时:

var id = "123";
var bar = this.mockContext.Object.Foo.Where(p => p.id == id);

我按预期返回一个带有单个结果的IQueryable()。但是当我尝试将我的对象投射到DTO时:

var id = "123";
var buzz = this.mockContext.Object.Foo.Where(p => p.id == id).ProjectTo<FooDto>(this.config);

如果我尝试以任何方式访问结果,那么我回来的IQueryable会抛出Null Reference Exception。例如:

buzz.ToList();
buzz.SingleOrDefault(); // This mirrors the actual call in my code since this is a GetById query.
两个都失败了。我在这里缺少什么?

1 个答案:

答案 0 :(得分:0)

问题在于Foo使用EF导航属性来引用其他对象。特别是在这种情况下PhoneNumber。由于在没有链接的PhoneNumber对象的情况下创建测试数据,因此它会在ProjectTo方法内部中断。当直接抓取顶层Queryable时,这不是一个问题,但Automapper需要对象存在(即使它们为空),以便完成映射。将该行更改为:

data.Add(new Foo() { Id = id, PhoneNumber = new PhoneNumber() });

允许ProjectTo方法完成,尽管是空值。