Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to resolve service for type 'Core.Data.CoreContext' while attempting to activate 'Core.Data.Repositories.UnitOfWork' #2140

Closed
borisdj opened this issue Aug 17, 2017 · 4 comments

Comments

@borisdj
Copy link

borisdj commented Aug 17, 2017

I have part of WebAPI application that I want to move to separate project as class library.
It is common base structure that almost every app has so idea is to make it easy shareable.
Application type is:
ASP.NET Core Web Application / .NET Framework - ASP.NET Core 2.0 / Web API

What I have done in that direction is created a project named Core and moved those shared elements there, including Base Entities (e.g. User, Settings, etc), CoreContext, UnitOfWork, Generic Repository, BaseRepositories,...

In the Main project of app there are others Entities, AppContext that inherits CoreContext, more Repositories, and all Controllers, ...

I was able to build the app but when starting it get the following error:

InvalidOperationException: Unable to resolve service for type 'Core.Data.CoreContext' while attempting to activate 'Core.Data.Repositories.UnitOfWork'.

Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)...

Problem seems to be that UnitOfWork class is in Core project and in Main project is Startup.cs with method ConfigureServices that has services.AddTransient<IUnitOfWork, UnitOfWork>();.

Is this a bug or am I just not configuring it correctly and how could it be achieved, if possible at all?

Further technical details

NetCore & EF Core version: 2.0
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
IDE: Visual Studio 2017 15.3
Operating system: Windows 10

CODE Sample:

namespace Main
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build();
    }
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IUnitOfWork, UnitOfWork>();
            services.AddMvc();
            var conn = Configuration.GetConnectionString("DefaultConnection"); 
            services.AddDbContext<AppContext>(options => options.UseSqlServer(conn));
        }
    }
}

namespace Main.Data
{
    public class AppContext : CoreContext
    {
        ...
    }
}
namespace Core.Data
{
    public class UnitOfWork : IUnitOfWork, IDisposable
    {
        public CoreContext context;

        public UnitOfWork(CoreContext context)
        {
            this.context = context;
        }

        public T Get<T>() where T : BaseRepository, new()
        {
            var repository = new T();
            repository.Init(context);
            return repository;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}
@borisdj
Copy link
Author

borisdj commented Oct 8, 2017

Solution was:
Your code has is expecting to inject s CorecContext but you configured an AppContext in your code. Dependency injection doesn’t work that way. You need to specify the service type as CoreContext.
from dotnet/core repository issues/996

So instead of
services.AddDbContext<AppContext>(options => options.UseSqlServer(conn));
it should be
services.AddDbContext<CoreContext>(options => options.UseSqlServer(conn));

@borisdj
Copy link
Author

borisdj commented Oct 12, 2017

@davidfowl
This fix solved original issue but now I have another problem.
When accessing context.Set<SomeEntity> (where DbSet<SomeEntity> SomeEntities is not in Core project but in Main project) getting following exception:

InvalidOperationException: Cannot create a DbSet for 'SomeEntity' because this type is not included in the model for the context.

Now all DbSets ,except those shared in Core project, are not accessible.
Any thoughts?

@tymarats
Copy link

tymarats commented Oct 13, 2017

Couldn't (or shouldn't :)) you actually use UnitOfWork<TContext> instead? Then you would have something along the lines of:

Your Core project:

public class UnitOfWork<TContext> : IUnitOfWork, IDisposable
    where TContext : CoreContext
{
   public UnitOfWork(TContext ctx) { ... }
   ...
}

Your App project

public class AppUnitOfWork : UnitOfWork<AppContext> { 
    public AppUnitOfWork(AppContext ctx) : base(ctx) { }
}
...
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
       ...
        services.AddTransient<IUnitOfWork, AppUnitOfWork>(); // Note the App prefix
        services.AddDbContext<AppContext>(options => options.UseSqlServer(conn)); // Note the App prefix
    }
    ...
}

This way, whenever your request IUnitOfWork as a dependency, say ctor MyRepoOrWhatever(IUnitOfWork uow), you will get a correct instance of AppUnitOfWork and AppContext.

@borisdj
Copy link
Author

borisdj commented Oct 17, 2017

Thx tymarats, this solved it.

@borisdj borisdj closed this as completed Oct 17, 2017
@ghost ghost locked as resolved and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants