0

I have an application with two DbContexts - ApplicationDbContext (from IdentityDbContext) and my own IMSDbContext (from a db-first scaffolding).

I am trying to inject a Repository (based on my own dbContext) into ApplicationUser without success:

startup.cs:

services.AddDbContext<IMSDBContext>(options => options.UseSqlServer(IMSConnString));
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(IdentityConnString));

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

Repository:

  public interface IGenericRepository<T> where T: class
    {
        Task<IList<T>> GetAll(
            Expression<Func<T, bool>> expression = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
            List<string> includes = null);

        Task<T> Get(Expression<Func<T, bool>> expression,List<string> includes=null);
        Task Insert(T entity); etc...


   public class GenericRepository<T> : IGenericRepository<T> where T : class
    {
        private readonly IMSDBContext _context;
        private readonly DbSet<T> _db;

        public GenericRepository(IMSDBContext context)
        {
            _context = context;
            _db = _context.Set<T>();

        }

        public async Task<IList<T>> GetAll(Expression<Func<T, bool>> expression = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, List<string> includes = null)
        {
            IQueryable<T> query = _db;

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

            if (includes != null)
            {
                foreach (var includeProperty in includes)
                {
                    query.Include(includeProperty);
                }
            }

            if (orderBy != null)
            {
                query=orderBy(query);
            }

            return await query.AsNoTracking().ToListAsync();
        } etc..

ApplicationUser.cs

 public class ApplicationUser : IdentityUser
{
    private IGenericRepository<Departments> _genericRepositoryDepts;

    public ApplicationUser(IGenericRepository<Departments> genericRepositoryDepts)
    {
        _genericRepositoryDepts = genericRepositoryDepts;
    }

    public Int16 Employee_id { get; set; }
    public List<int> DepartmentsManaged()
    {
        var c = _genericRepositoryDepts.GetAll(x=>x.Manager==this.Employee_id).Result.Select(x => x.id);
        return c.ToList();
    }

Running the code generates an exception in UserManager:

System.InvalidOperationException: 'No suitable constructor was found for entity type 'ApplicationUser'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'genericRepositoryDepts' in 'ApplicationUser(IGenericRepository<Departments> genericRepositoryDepts)'.'

Which I think is telling me that the DI container is not recognising ApplicationUser as being 'DI-enabled' and therefore leaving EF to try and match the constructor to entities in the DB. Does this mean I just can't DI into ApplicationUser like this?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Rich Freeman
  • 1,009
  • 2
  • 9
  • 22
  • Basically yes. I would suggest either combining the two databases or using a separate method to populate the DepartmentsManaged at the point you need the data – ste-fu Sep 28 '21 at 15:17
  • simplest solution is to add a parameterless private constructor. – Code Name Jack Sep 28 '21 at 15:58
  • 2
    On a side not, I would suggest you should not mix external services with your domain model, and the data should be injected instead of injecting the data context. – Code Name Jack Sep 28 '21 at 16:04
  • 1
    Did you try to use: services.AddScoped, GenericRepository>(); – ElConrado Sep 28 '21 at 16:23
  • Thanks @ste-fu the underlying db is basically just one db - but I know of no reasonable way I can combine the IdentityDBContext entities with the rest of my DB-first data base in such a way that I can continue to re-scaffold it as db changes happen. – Rich Freeman Sep 28 '21 at 17:06
  • Thanks @CodeNameJack - that fixes the error but the DI is still not working (so my repository is null come the time it's needed). Take the point re: mixing services but obvs moot if DI is inoperable here. – Rich Freeman Sep 28 '21 at 17:33
  • @ElConrado - yes I did - same result. – Rich Freeman Sep 28 '21 at 17:34
  • 1
    Entity Framework doesn't invoke the Dependency Injection framework when creating a model object. There are some hacky workarounds available, but you're better off following the pattern of separating your service classes (injectable) from your model classes (newable). In addition to the post I marked as a duplicate, see https://stackoverflow.com/q/36207289/120955 and https://stackoverflow.com/q/48480889/120955 – StriplingWarrior Sep 28 '21 at 18:17

0 Answers0