9 c# entity-framework automapper entity-framework-6 automapper-4
我正在尝试在Entity Framework IQueryables上使用Automapper投影.
在应用程序启动时,我创建并添加了所有映射配置文件,这些配置文件使用非静态CreateMap方法创建映射.
所有这些配置文件都在我的IoC容器中注册.
虽然我在mappingConfiguration的实例中看到了映射配置文件,但我得到了缺少的映射异常.
可能是什么问题呢?我错过了什么吗?我正在使用Automapper 4.2.1
我注意到在添加静态Mapper.CreateMap时,它工作正常.预测只适用于静态API吗?我想避免使用静态API.
完整代码:
public class ItemEntityToItemView : Profile
{
public override void Configure()
{
CreateMap<ItemEntity, ItemView>();
// Without this line, I get missing Map type configuration.
Mapper.CreateMap<ItemEntity, ItemView>();
}
}
public interface IEntitiesProjector
{
IQueryable<T> SelectTo<T>(IQueryable source);
}
public class EntitiesProjector : IEntitiesProjector
{
private readonly IMapperConfiguration _mapperConfig;
public EntitiesProject(IMapperConfiguration mapperConfig)
{
_mapperConfig = mapperConfig;
}
public IQueryable<T> SelectTo<T>(IQueryable source)
{
return source.ProjectTo<T>(_mapperConfig);
}
}
public class ItemsRepository : IITemsRepository
{
public IQueryable<ItemEntity> GetById(int id)
{
return _dbSet.Where(x => x.Id == id);
}
}
public class Service
{
private readonly IEntitiesProjector _projector;
public Service(IEntitiesProject entitiesProjector)
{
_projector = entitiesProjector;
}
public List<T> GetItem(int id)
{
IQueryable<ItemEntity> itemsQueryable = ItemsRepository.GetById(id);
return _projector.SelectTo<ItemView>(itemsQueryable);
}
}
My Autofac registration :
builder.RegisterAssemblyTypes().AssignableTo(typeof(Profile)).As<Profile>();
builder.Register(c => new MapperConfiguration(cfg =>
{
cfg.CreateMap<IdentityUser, AspNetUser>().ReverseMap();
})).AsSelf().As<IMapperConfiguration>().SingleInstance();
builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve)).As<IMapper>().InstancePerLifetimeScope();
builder.Register<EntitiesProjector>().As<IEntitiesProjector>().SingleInstance();
Run Code Online (Sandbox Code Playgroud)
原因如下:
public class EntitiesProjector : IEntitiesProjector
{
private readonly IMapperConfiguration _mapperConfig;
public EntitiesProject(IMapperConfiguration mapperConfig)
{
_mapperConfig = mapperConfig;
}
public IQueryable<T> SelectTo<T>(IQueryable source)
{
return source.ProjectTo<T>(_mapperConfig);
}
}
Run Code Online (Sandbox Code Playgroud)
source.ProjectTo是一种有5次重载的扩展方法.在文档中,他们在那里传递MappingConfiguration类的实例,并且您正在传递IMapperConfiguration(接口)的实例.你认为它会产生同样的效果,但事实并非如此.IMapperConfiguration接口没有实现IConfigurationProvider接口,而(IConfigurationProvider)是ProjectTo接受的正确重载.但是,还有另一个重载ProjectTo,它接受" object parameters".因为它接受对象 - 它将匹配任何不适合其他重载的东西.所以你真正称之为ProjectTo(object)重载,这与配置无关,而且你的IMapperConfiguration配置文件和地图一起完全被忽略了.
Quickfix将是
public class EntitiesProjector : IEntitiesProjector
{
private readonly IConfigurationProvider _mapperConfig;
public EntitiesProjector(IMapperConfiguration mapperConfig)
{
_mapperConfig = (IConfigurationProvider)mapperConfig;
}
public IQueryable<T> SelectTo<T>(IQueryable source)
{
return source.ProjectTo<T>(_mapperConfig);
}
}
Run Code Online (Sandbox Code Playgroud)
但是当然你应该更好地IConfigurationProvider在容器中注册你的配置,这只是快速解决方案,以确保问题确实在这里.
至于静态Mapper.CreateMap- 它是静态的,所以无论你传递什么都可以ProjectTo.
作为旁注,这将向您展示如何不设计api.每当你有很多重载并且其中一个接受通用对象并且完全不同于所有其他重载 - 这就是要求麻烦.