1
votes

My application has two databases: MainDbContext which inherits from DbContext and IdentifiedDbContext which inherits from MainDbContext.

MainDbContext uses base classes like EntityBase with Id, createdAt, updatedAt. IdentifiedDbContext uses IdentifiedEntityBase classes that inherit from EntityBase with properties CreatorId, OwnerId.

My application also has a Repository, and IdentifiedRepository which inherits from Repository.

Code looks like this:

public class BeehouseContext:DbContext
{
    public BeehouseContext(DbContextOptions<BeehouseContext> options) : base(options)
    {
        // -- Construtor
    }

    protected BeehouseContext(DbContextOptions options):base(options)
    {
        // -- Construtor fix
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        #region EntityBase
        modelBuilder.Ignore<Beehouse.Framework.Domain.EntityBase>();
        #endregion
    }
}

{

    public BeehouseIdentityContext(DbContextOptions<BeehouseIdentityContext> options) : base(options)
    {
        // -- Construtor
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        #region EntityBase
        modelBuilder.Ignore<Beehouse.Framework.Identity.Domain.IdentifiedEntity>();
        #endregion
    }
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : EntityBase
{
    protected readonly BeehouseContext Context;

    public Repository(BeehouseContext context)
    {
        Context = context;
    }

    private DbSet<TEntity> _entities;

    protected virtual DbSet<TEntity> Entities
    {
        get
        {
            if (_entities is null)
            {
                _entities = Context.Set<TEntity>();
            }
            return _entities;
        }
        }
// Other methods
    }
public class IdentifiedRepository<TEntity>:Repository<TEntity>, IIdentifiedRepository<TEntity> where TEntity:IdentifiedEntity
{
    protected readonly string UserId; // as Dealer
    protected readonly string CreatorId; // as Retailer
    protected readonly string CreatorAlias;

    public IdentifiedRepository(IHttpContextAccessor httpContextAccessor, BeehouseIdentityContext context):base(context)
    {
        if (httpContextAccessor.HttpContext.User.FindFirst("sub") == null) return;
        CreatorId = httpContextAccessor.HttpContext.User.FindFirst("sub").Value;
        CreatorAlias = httpContextAccessor.HttpContext.User.FindFirst(SubscriptionClaimTypes.ProfileName).Value;
        UserId = httpContextAccessor.HttpContext.User.FindFirst(SubscriptionClaimTypes.DealerUserId).Value;
    }

In dependency injection I can create an instance of IdentifiedRepository, but in some cases I need to instantiate the Repository only, but I can't. The following error is thrown:

InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Beehouse.Framework.Identity.Data.BeehouseIdentityContext]' while attempting to activate 'Beehouse.Framework.Identity.Data.BeehouseIdentityContext'.

I've tried to edit constructors like:

BeehouseContext(DbContextOptions options) : base(options)
BeehouseIdentityContext(DbContextOptions options) : base(options)

But this doesn't work either.

My dependency injection looks like this and doesn't work:

    // Database
services.AddDbContext<IdentityServerContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("connstring"))); 
services.AddTransient(typeof(BeehouseContext), typeof(BeehouseIdentityContext));

I also tried to add DbContext like this:

services.AddDbContext<IdentityServerContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("auxiliarc-local")));
        services.AddDbContext<BeehouseContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("auxiliarc-local")));

But that fails too with the following error:

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

Plan are in namespace and Project Identified, but inherits from EntityBase only.

Can somebody help-me? Thanks.

1
Quick fix: EF Core does not need to be hidden behind a Repository. You are creating both a maintenance nightmare and gaining absolutely nothing out of that. Solution: remove those repositories and use EF as it is intended to be used - Camilo Terevinto
@CamiloTerevinto: One of the benefits of hiding it behind a repository is abstracting out the data store, although I do agree with you that in practice, it almost never works out that way. - JuanR
@CamiloTerevinto: that's disputable, not a fix but a subjective recommendation then. - Wiktor Zychla
@JuanR Like if that was a real concern... Just switch UseSqlServer for UseInMemoryDatabase and done - Camilo Terevinto
I get this concept from NopCommerce Project - Wow, no wonder why you are confused. NopCommerce is a good example of a bad example. - NightOwl888

1 Answers

1
votes

The injector is looking to create an instance of type BeehouseIdentityContext.

The constructor requires an object of type DbContextOptions. The injector cannot instantiate this type for the activation of BeehouseIdentityContext so it throws an error.

Either tell the injector how to create instances of type DbContextOptions or create a constructor that uses defaults and does not need this type.