QueryableExtensions项目不投影地图

时间:2016-12-13 10:57:19

标签: c# automapper entity-framework-core projection

在内存中使用automapper 5.2.0与EF core 1.0.1和SQL lite结合使用。我无法创建预期的数据库查询,而是我得到了这个:

  

Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory:警告:   导航的包含操作:' a.PostTags.Tag'被忽略了   因为在最终查询中无法访问目标导航   结果。要配置此警告,请使用   DbContextOptionsBuilder.ConfigureWarnings API(事件ID   ' CoreEventId.IncludeIgnoredWarning&#39)。可以使用ConfigureWarnings   当重写DbContext.OnConfiguring方法或使用时   应用程序服务提供程序上的AddDbContext。   Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory:警告:   导航的包含操作:' a.Responses.CreatedByUser'是   被忽略,因为目标导航在最终中无法访问   查询结果。要配置此警告,请使用   DbContextOptionsBuilder.ConfigureWarnings API(事件ID   ' CoreEventId.IncludeIgnoredWarning&#39)。可以使用ConfigureWarnings   当重写DbContext.OnConfiguring方法或使用时   应用程序服务提供程序上的AddDbContext。   Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory:警告:   导航的包含操作:' a.CreatedByUser'被忽略了   因为在最终查询中无法访问目标导航   结果。要配置此警告,请使用   DbContextOptionsBuilder.ConfigureWarnings API(事件ID   ' CoreEventId.IncludeIgnoredWarning&#39)。可以使用ConfigureWarnings   当重写DbContext.OnConfiguring方法或使用时   应用程序服务提供程序上的AddDbContext。   Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory:警告:   导航的包含操作:' a.Category'被忽略了因为   最终查询结果中无法访问目标导航。至   配置此警告使用   DbContextOptionsBuilder.ConfigureWarnings API(事件ID   ' CoreEventId.IncludeIgnoredWarning&#39)。可以使用ConfigureWarnings   当重写DbContext.OnConfiguring方法或使用时   应用程序服务提供程序上的AddDbContext。   Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory:信息:   执行DbCommand(0ms)[Parameters = [@__ id_0 ='?'],   CommandType =' Text',CommandTimeout =' 30'] SELECT 1 FROM"帖子" AS" a"   在哪里" a"。" PostId" = @__ id_0 LIMIT 2

这是我的设置:

启动:

public class Startup
{
    private MapperConfiguration _mapperConfiguration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        ...
        _mapperConfiguration = new MapperConfiguration(cfg =>
        {
            ...
            cfg.AddProfile(new PostMapperProfile());
        });

        _mapperConfiguration.AssertConfigurationIsValid();
    }


    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddSingleton<IMapper>(sp => _mapperConfiguration.CreateMapper());
        services.AddSingleton<MapperConfiguration>(sp => _mapperConfiguration);
    }
}

PostMapperProfile:

public class PostMapperProfile : Profile
{
    public PostMapperProfile()
    {
        var postDetailMap = CreateMap<PostEntity, PostDetailModel>();
        postDetailMap.ForAllMembers(opt => opt.Ignore());
        postDetailMap.ForMember(m => m.Category, opt => opt.MapFrom(src => src.CategoryId.HasValue ? src.Category : null));
        postDetailMap.ForMember(m => m.CreatedAt, opt => opt.MapFrom(src => src.CreatedAt));
        postDetailMap.ForMember(m => m.CreatedByUser, opt => opt.MapFrom(src => src.CreatedByUser));
        postDetailMap.ForMember(m => m.PostId, opt => opt.MapFrom(src => src.PostId));
        postDetailMap.ForMember(m => m.PostState, opt => opt.MapFrom(src => src.PostState));
        postDetailMap.ForMember(m => m.PostType, opt => opt.MapFrom(src => src.PostType));
        postDetailMap.ForMember(m => m.ResponsesCount, opt => opt.MapFrom(src => src.Responses.Count));
        postDetailMap.ForMember(m => m.Text, opt => opt.MapFrom(src => src.Text));
        postDetailMap.ForMember(m => m.Tags, opt => opt.MapFrom(src => src.PostTags.Select(x => x.Tag).ToList()));
        postDetailMap.ForMember(m => m.Title, opt => opt.MapFrom(src => src.Title));
        postDetailMap.ForMember(m => m.ViewsCount, opt => opt.MapFrom(src => src.ViewsCount));
        postDetailMap.ForMember(m => m.VotesCount, opt => opt.MapFrom(src => src.VotesCount));
        postDetailMap.ForMember(m => m.Responses, opt => opt.MapFrom(src => PagedList<ResponseEntity>.Create(src.Responses.Take(10).Select(x => AutoMapper.Mapper.Map<ResponseDetailModel>(x)).ToList(), 1, 10, src.Responses.Count)));
    }
}

BlogpostService:

public class BlogpostService
{
    private readonly AppDbContext m_context;
    private readonly IMapper m_mapper;
    private readonly MapperConfiguration m_config;      

    public BlogpostService(AppDbContext context, IMapper mapper, MapperConfiguration config)
    {
        m_context = context;
        m_mapper = mapper;
        m_config = config;
    }

    public PostDetailModel GetPostDetail(int id)
    {
        var s = m_context.Posts
            .Include(a => a.CreatedByUser)
            .Include(a => a.Category)
            .Include(a => a.PostTags)
            .ThenInclude(a => a.Tag)
            .Include(a => a.Responses)
            .ThenInclude(b => b.CreatedByUser)            
            .Where(x => x.PostId == id);
            var d = s.Single();
        return s.ProjectTo<PostDetailModel>(m_config).Single();
    }
}

测试:

public class PostRepositoryTests
{
    public TestServer server { get; }
    public HttpClient client { get; }
    private readonly AppDbContext Context;
    private readonly UserManager<UserEntity> UserManager;
    private readonly IMapper Mapper;
    private readonly MapperConfiguration Config;

    public PostRepositoryTests()
    {
        ...
        Context = serviceProvider.GetRequiredService<AppDbContext>();
        UserManager = serviceProvider.GetRequiredService<UserManager<UserEntity>>();
        Mapper = serviceProvider.GetService<IMapper>();
        Config = serviceProvider.GetService<MapperConfiguration>();
    }

    [Fact] 
    public void CreatePost()
    {
        var user = new UserEntity();
        user.Email = "test@test.com";

        var ct = UserManager.CreateAsync(user, "Testing123..");

        var service = new BlogpostService(Context, Mapper, Config);
        var blogpost = new CreateBlogpostRequest();
        blogpost.Title = "Some title";
        blogpost.Content = "Some content";
        blogpost.Tags = new List<TagDTO>(){
            new TagDTO{
                Label = "Tag1",
            },
            new TagDTO{
                Label = "Tag2",
            },
            new TagDTO{
                Label = "Tag3",
            }
        };

        var response = service.CreateBlogpost(blogpost, user.Id);
        var postDetail = service.GetPostDetail(response.PostId);
        Assert.Equal(postDetail.Tags.Count, 3);
    }
}

1 个答案:

答案 0 :(得分:1)

@IvanStoev向我指出正确的方向,我设法解决它,我想

postDetailMap.ForAllMembers(opt => opt.Ignore());

以某种方式掩盖了其他错误,在我删除该行之后,我收到错误,指出某些属性未映射,因此我为这些成员和Responses属性添加了显式忽略。

之后它实际上尝试进行查询但是由于标签中的.ToList()失败(我意外地补充说,当从MVC4,AM 4.x升级时),所以在摆脱.ToList()之后,事情就会起作用。 / p>

有效的修改后的地图:

    var postDetailMap = CreateMap<PostEntity, PostDetailModel>();
    postDetailMap.ForMember(m => m.ResponsesShowing,opt => opt.Ignore());
    postDetailMap.ForMember(m => m.Responses, opt => opt.Ignore());
   // postDetailMap.ForAllMembers(opt => opt.Ignore());
    postDetailMap.ForMember(m => m.Category, opt => opt.MapFrom(src => src.CategoryId.HasValue ? src.Category : null));
    postDetailMap.ForMember(m => m.CreatedAt, opt => opt.MapFrom(src => src.CreatedAt));
    postDetailMap.ForMember(m => m.CreatedByUser, opt => opt.MapFrom(src => src.CreatedByUser));
    postDetailMap.ForMember(m => m.PostId, opt => opt.MapFrom(src => src.PostId));
    postDetailMap.ForMember(m => m.PostState, opt => opt.MapFrom(src => src.PostState));
    postDetailMap.ForMember(m => m.PostType, opt => opt.MapFrom(src => src.PostType));
    postDetailMap.ForMember(m => m.ResponsesCount, opt => opt.MapFrom(src => src.Responses.Count));
    postDetailMap.ForMember(m => m.Text, opt => opt.MapFrom(src => src.Text));
    postDetailMap.ForMember(m => m.Tags, opt => opt.MapFrom(src => src.PostTags.Select(x => x.Tag)));
    postDetailMap.ForMember(m => m.Title, opt => opt.MapFrom(src => src.Title));
    postDetailMap.ForMember(m => m.ViewsCount, opt => opt.MapFrom(src => src.ViewsCount));
    postDetailMap.ForMember(m => m.VotesCount, opt => opt.MapFrom(src => src.VotesCount));
    //postDetailMap.ForMember(m => m.Responses, opt => opt.MapFrom(src => PagedList<ResponseEntity>.Create(src.Responses.Take(10).Select(x => AutoMapper.Mapper.Map<ResponseDetailModel>(x)).ToList(), 1, 10, src.Responses.Count)));