简体   繁体   中英

Dependency Injection with GenericRepository error - No database provider has been configured for this DbContext NET.Core 3.1

I've got an error while start my application with GenericRepository. (No database provider has been configured for this DbContext.).

How can i modify mine GenericRepository to be able to resolve that? Here's my codes:

IRepository.cs

public interface IRepository<TEntity> where TEntity : class
{

    /*void Delete(TEntity entityToDelete);
    void Delete(object id);*/
    IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "");

    TEntity GetById(object id);
    Task<TEntity> GetByIdAsync(object id);

    /*IEnumerable<TEntity> GetWithRawSql(string query,
        params object[] parameters);*/
    void Insert(TEntity entity);
    TEntity Update(long id, Action<TEntity> action);
    }

Generic Repository.cs

public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        internal Context context;
        internal DbSet<TEntity> dbSet;

        public GenericRepository(Context context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>(); // here's the error (No database provider...)
        }

        public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
            string includeProperties = "")
        {
            IQueryable<TEntity> query = dbSet;

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            if (orderBy != null)
            {
                return orderBy(query).ToList();
            }
            else
            {
                return query.ToList();
            }
        }

        public virtual TEntity GetById(object id)
        {
            return dbSet.Find(id);
        }

        public async Task<TEntity> GetByIdAsync(object id)
        {
            return await dbSet.FindAsync(id);
        }

        public virtual void Insert(TEntity entity)
        {
            dbSet.Add(entity);
            context.SaveChanges();
        }

        public virtual void Remove(object id)
        {
            TEntity entityToDelete = GetById(id);
            Remove(entityToDelete);
        }

        public void Remove(TEntity entityToDelete)
        {
            if (context.Entry(entityToDelete).State == EntityState.Detached)
            {
                dbSet.Attach(entityToDelete);
            }
            dbSet.Remove(entityToDelete);
        }

        public virtual void Update(TEntity entity)
        {
            dbSet.Attach(entity);
            context.Entry(entity).State = EntityState.Modified;
        }

        public TEntity Update(long key, Action<TEntity> action)
        {
            var model = dbSet.Find(key);
            if(model != null)
            {
                Update(model);
                action(model);
            }
            return model;
        }

    }

DependencyResolver.cs

public class DependencyResolver
    {
        public IServiceProvider ServiceProvider { get; }

        public DependencyResolver()
        {
            // Set up Dependency Injection
            IServiceCollection services = new ServiceCollection();

            ConfigureServices(services);
            ServiceProvider = services.BuildServiceProvider();
        }

        private void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient(typeof(IRepository<>), typeof(GenericRepository<>));

            // Register DbContext class
            services.AddTransient(provider =>
            {
                var configService = provider.GetService<IConfigurationService>();
                //var connectionString = configService.GetConfiguration().GetConnectionString("uRP");
                var optionsBuilder = new DbContextOptionsBuilder<Context>();
                optionsBuilder.UseMySql("server=localhost;database=uRP;user=root;password=;", builder => builder.MigrationsAssembly(typeof(Context).GetTypeInfo().Assembly.GetName().Name));

                return new Context(optionsBuilder.Options);
            });

            services.AddScoped<IAccountService, AccountService>();
            services.AddScoped<IUnitOfWork, UnitOfWork.UnitOfWork>();

        }
    }

Context.cs

public class Context : DbContext
{
public Context(DbContextOptions<Context> options) : base(options)
{

}

public Context()
{

}



public DbSet<AccountModel> Players { get; set; }
public DbSet<CharacterModel> Characters { get; set; }
}

And ContextTimeDesignFactory.cs

    class ContextDesignTimeFactory : IDesignTimeDbContextFactory<Context>
{
    public Context CreateDbContext(string[] args)
    {
        var resolver = new DependencyResolver();
        return resolver.ServiceProvider.GetService(typeof(Context)) as Context;
    }
}

There are all good. I've got an IAccountRepository, and ICharacterRepository and it's work good. How i can set the DbContextOptions in GenericRepository.cs?

Seems like a mistake with registration of Context.

You have DependencyResolver which used in ContextDesignTimeFactory. But how do you register Context within application?

When I try to register Context like this:

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddTransient(provider =>
    {
        var optionsBuilder = new DbContextOptionsBuilder<Context>();
        optionsBuilder.UseMySql(
            "server=localhost;database=uRP;user=root;password=;",
            builder => builder.MigrationsAssembly(typeof(Context).GetTypeInfo().Assembly.GetName().Name));

        return new Context(optionsBuilder.Options);
    });

    services.AddTransient(typeof(IRepository<>), typeof(GenericRepository<>));
}

there is no errors with resolving GenericRepository.

But when I change registration to

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddTransient<Context>();

    services.AddTransient(typeof(IRepository<>), typeof(GenericRepository<>));
}

I've got exactly same exception at the same place.

Hope it help

PS For DbContext registration has a specific method AddDbContext

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM