Automapper 在 Profile 类中注入 DbContext

6
我有下面这个映射配置文件:

public class DomainProfile : Profile
{
    private FootballPredictionsContext m_Context;

    public DomainProfile(FootballPredictionsContext context)
    {
        m_Context = context;
    }

    public DomainProfile()
    {
        CreateMap<TipModel, Tip>()
            .ForMember(tip => tip.BetType, m => m.MapFrom(x => m_Context.BetTypes.First(y => y.Name == x.BetType)))
            .ForMember(tip => tip.BetCategory, m => m.MapFrom(x => m_Context.BetCategories.First(y => y.Name == x.BetCategory)))
            .ForMember(tip => tip.Sport, m => m.MapFrom(x => m_Context.Sports.First(y => y.Name == x.Sport)))
            .ForMember(tip => tip.Tipster, m => m.MapFrom(model => m_Context.Tipsters.First(y => y.Username == model.Tipster)));
    }
}

如您所见,一些映射正在使用 DbContext,因此我必须在 DomainProfile 中注入它。
在启动类中,我正常地初始化了 Automapper。
public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped(typeof(IUnificator), typeof(Unificator));
            services.AddDbContext<FootballPredictionsContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Database")));
            services.AddDbContext<UnificationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Database")));

            services.AddSingleton(provider => new MapperConfiguration(cfg =>
                {
                    cfg.AddProfile(new UserProfile(provider.GetService<IUserManager>()));
                }).CreateMapper());
            services.AddMvc();
        }

我尝试了这个解决方案,但是我收到了'Cannot resolve scoped service 'FootballPredictions.DAL.FootballPredictionsContext' from root provider.'的错误信息。


1
最近我遇到了一个类似的问题,原因是我正在尝试将一个服务注入到寿命更长的服务中(例如瞬态和作用域)。DomainProfile类关联的是哪种生命周期?你尝试过将其更改为Scoped或Transient,看看是否有帮助? - Simply Ged
将你的依赖项移动到解析器或类型转换器中。请查看此处。配置文件是单例模式。 - Lucian Bargaoanu
@SimplyGed 是的,这解决了问题!谢谢。 - Dimitar Tsonev
2个回答

7

最近我遇到了一个类似的问题,原因是我试图将一个生命周期更长的服务(例如:瞬态和作用域)注入到另一个服务中。DomainProfile类对应哪种生命周期?您尝试将其更改为Scoped或Transient来查看是否有所帮助吗?

@DimitarTsonev的实现方式是这样的:

因此,将映射器作用域更改为

services.AddScoped(provider => new MapperConfiguration(cfg =>
    {
        cfg.AddProfile(new DomainProfile(provider.GetService<FootballPredictionsContext>()));
    }).CreateMapper());

修复了问题


你可以使用我提供的代码更改你的答案,我会接受它作为答案。 - Dimitar Tsonev
当在ASP.NET Web应用程序中使用时,这会对性能产生巨大影响,因为.CreateMapper()基本上在每个HTTP请求上被调用,并将我的服务调用从4-5毫秒增加到20毫秒(减速4倍)。因此请谨慎使用。 - Dynalon

0
假设您已经实际注册了上下文(例如services.AddDbContext),那么导致该异常的最可能原因是在注册上下文之前注册了AutoMapper。确保首先注册上下文,然后再执行类似于services.AddAutoMapper的操作。

如果您查看提供的代码,您会注意到它们已按正确的顺序注册。 - Dimitar Tsonev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接