简体   繁体   中英

IdentityUser generic repository when we create Controller in Asp.Net MVC Core

Here is Repository pattern, Normally if I used ContextDb instead of IdentityContextDb ,it would have worked but i have to use Indentity for creating my Identificial things.

Core.Repository

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;



namespace XYZ.CORE.Repository
 {
     public class Repository<TEntity, TContext> : IRepository<TEntity> where 
 TEntity : class, new() where TContext : IdentityDbContext, new()
     {
         public void Delete(TEntity entity)
         {
             using (var context=new TContext())
             {
                 var deleteEntity = context.Entry(entity);
                 deleteEntity.State = EntityState.Deleted;
                 context.SaveChanges();
             }
         }

     public IEnumerable<TEntity> GetAll(Expression<Func<TEntity, bool>> filter = null)
    {
        using (var context = new TContext())
        {
            return filter == null ? context.Set<TEntity>().AsEnumerable() : context.Set<TEntity>().Where(filter).AsEnumerable();
        }
    }

    public TEntity GetById(int id)
    {
        using (var context = new TContext())
        {
            return context.Set<TEntity>().Find(id);
        }
    }

    public void Insert(TEntity entity)
    {
        using (var context = new TContext())
        {
            var addEntity = context.Entry(entity);
            addEntity.State = EntityState.Added;
            context.SaveChanges();
        }
    }

    public void Update(TEntity entity)
    {
        using (var context = new TContext())
        {
            var updatedEntity = context.Entry(entity);
            updatedEntity.State = EntityState.Modified;
            context.SaveChanges();
        }
    }
}
}

again but :) when i inherit my context from IdentityContextDb, it wants generic type like bottom of this line and its problem for Repository.

i'll share what is like an error when we call this Repo

DAL.Context

using XYZ.DATA.Entity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;

namespace XYZ.DAL.Context
{
   public class XyzDb:IdentityDbContext<AppUser>
    {
        public HysWebDb(DbContextOptions options) : base(options)
        {

        }

    }
}

and now lets call in Controller

UI.Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using XYZ.UI.Models.VM;
using Microsoft.AspNetCore.Mvc;
using XYZ.DAL.Context;
using Microsoft.AspNetCore.Identity;
using XYZ.DATA.Entity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using XYZ.CORE.Repository;

namespace XYZ.UI.Controllers.Account
{
     //[Authorize(Roles ="Admin")]
    public class RegisterController : Controller
    {
        private readonly XyzDb _database;
        private readonly UserManager<AppUser> _uManager;
        private readonly Repository<AppUser,XyzDb> _userRepo;
        public RegisterController(UserManager<AppUser> uManager, XyzDb database)
        {
            _database = database;
            _uManager = uManager;

        }
   }

}

although we havent injected yet but ...

Error CS0311 The type 'XYZ.DAL.Context.XyzDb' cannot be used as type parameter 'TContext' in the generic type or method 'Repository'. There is no implicit reference conversion from 'XYZ.DAL.Context.XyzDb' to 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext'. ~\\XYZ.UI\\Controllers\\Account\\RegisterController.cs 21 Active

Error CS0310 'XyzDb' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TContext' in the generic type or method 'Repository' ~\\XYZ.UI\\Controllers\\Account\\RegisterController.cs 21 Active

Line 21 is here private readonly Repository _userRepo;

Thanks,

Özgür

Actually you're setting a constraint on your generic Repository class

public class Repository<TEntity, TContext> : IRepository<TEntity> where
TEntity : class, new() where TContext : IdentityDbContext, new()

which is the new() on your IdentityDbContext, so your IdentityDbContext should contains a parameterless constructor. For more details check microsoft docs https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/new-constraint

 public class Repository<TEntity, TContext> : IRepository<TEntity> where 
 TEntity : class, new() where TContext : IdentityDbContext, new()

You are defining here two things:

  1. The repository class must use class there TEntity & TContext has new() which means parameterless constructor, when in fact you have only 1 constructor with options - (this is your 2nd error)

public HysWebDb(DbContextOptions options) : base(options)

  1. The second problem not 100% sure about this but if you inherit a generic interface but declare the type - IdentityDbContext - it cannot be considered as only IdentityDbContext

public class XyzDb:IdentityDbContext < AppUser>

To solve your problem you should change the public class Repository to this:

 public class Repository<TEntity, TContext> : IRepository<TEntity> where 
 TEntity : class, new() where TContext : IdentityDbContext<AppUser>

I can solve with using context referance and injection in constructor

public class Repository<T> : IRepository<T> where T : class { private readonly ContextX _database; public Repository(ContextX database) { _database = database; }

we cant find another way for solution

Thanks,

Özgür Deniz

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