6

I have the following mapping profile

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)));
    }
}

As you can see, some of the mappings are using the DbContext, so I have to somehow inject it in the DomainProfile

In the Startup class I am initializing the Automapper normally

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();
        }

I tried this solution, but I am receiving 'Cannot resolve scoped service 'FootballPredictions.DAL.FootballPredictionsContext' from root provider.'

Dimitar Tsonev
  • 3,711
  • 5
  • 40
  • 70
  • 1
    I've come across a similar problem recently and it was down to the fact that I was trying to inject a service into a service with a longer lifetime (e.g. transient and scoped). What lifetime is associated with the DomainProfile class? Have you tried changing that to Scoped or Transient to see if that helps? – Simply Ged Mar 09 '18 at 16:22
  • Move your dependencies in resolvers or type converters. See [here](http://automapperdocs.readthedocs.io/en/latest/Dependency-injection.html). Profiles are singletons. – Lucian Bargaoanu Mar 09 '18 at 16:29
  • @SimplyGed yes, this fixed the issue! Thanks – Dimitar Tsonev Mar 09 '18 at 16:33

2 Answers2

7

I've come across a similar problem recently and it was down to the fact that I was trying to inject a service into a service with a longer lifetime (e.g. transient and scoped). What lifetime is associated with the DomainProfile class? Have you tried changing that to Scoped or Transient to see if that helps?

As implemented by @DimitarTsonev: So, changing the mapper scope to

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

fixed the issue

Simply Ged
  • 8,250
  • 11
  • 32
  • 40
  • You can change your answer with the code provided in mine, and I will Accept it as answer. – Dimitar Tsonev Mar 09 '18 at 16:39
  • When used in a ASP.NET web app, this massively impacts performance as the `.CreateMapper()` is basically called on every HTTP request and increased my service calls from 4-5ms to 20ms (4x slowdown). So use with caution. – Dynalon Jun 23 '22 at 12:20
0

Assuming you've actually registered you context (services.AddDbContext, for example), the most likely cause of that exception is that you're registering AutoMapper before you're registering the context. Make sure your context is registered first, before you do something like services.AddAutoMapper.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444