简体   繁体   中英

Generic repository and unit of work in netcore

I'm noob in netcore, i'm using generic repository and unit of work in netcore. but i'm having problems, my project is compose for 3 layers, Api, BLL, DA, i have this error. Unable to resolve service for type 'ProyectosInvestigacion.DAL.ProyectosInvestigacionContext' while attempting to activate 'ProyectosInvestigacion.DAL.Class.UnitOfWork'.

Thanks for you support

Project DA

IRepository

public interface IRepository<TEntity> where TEntity : class
{
    IQueryable<TEntity> FindAll(string[] IncludeProperties = null);
    IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate, string[] IncludeProperties = null);
    TEntity FindById(int Id);
    void Create(TEntity entity);
    void Update(TEntity entity);
    void Delete(TEntity entity);
    void Delete(int Id);

}

Repository

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private DbSet<TEntity> _DbSet;
    private readonly ProyectosInvestigacionContext dbContext;

    public Repository(ProyectosInvestigacionContext ProyectosInvestigacionContext)
    {
        this.dbContext = ProyectosInvestigacionContext;
        this._DbSet = dbContext.Set<TEntity>();
    }

    /// <summary>
    /// Add new entity 
    /// </summary>
    /// <param name="entity">Entity to add </param>
    public virtual void Create(TEntity entity)
    {
        _DbSet.Add(entity);
    }

    /// <summary>
    /// Add new List of Entity
    /// </summary>
    /// <param name="entity"></param>
    public virtual void Create(IEnumerable<TEntity> entity)
    {
        foreach (var item in entity)
        {
            _DbSet.Add(item);
        }

    } ....

IUnitOfWork

public interface IUnitOfWork : IDisposable
{
    void SaveChanges();

    IRepository<Grupo> GrupoRepository { get; }
}

UnitOfWork

 public class UnitOfWork: IUnitOfWork
{
    private readonly  ProyectosInvestigacionContext dbContext;
    private bool disposed;
    private Dictionary<string, object> repositories;

    private IRepository<Grupo> _grupoRepository;

    ///// <summary>
    ///// Constructor
    ///// </summary>
    ///// <param name="ProyectosInvestigacionContext">Context Class</param>
    public UnitOfWork(ProyectosInvestigacionContext Context)
    {
        this.dbContext = Context;
    }

    /// <summary>
    /// Execute pending changes 
    /// </summary>
    public void SaveChanges()
    {
        dbContext.SaveChanges();
    }

    /// <summary>
    /// Get Current Context
    /// </summary>
    /// <returns></returns>
    public ProyectosInvestigacionContext GetContext()
    {
        return this.dbContext;
    }

    public IRepository<Grupo> GrupoRepository => _grupoRepository ?? 
                                                    (_grupoRepository = new Repository<Grupo>(dbContext));

    /// <summary>
    /// Disposing 
    /// </summary>
    /// <param name="disposing">Bool to dispose</param>
    public virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                dbContext.Dispose();
            }
        }
        disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

ProyectosInvestigacionContext

public partial class ProyectosInvestigacionContext : DbContext
{

    public ProyectosInvestigacionContext(DbContextOptions<ProyectosInvestigacionContext> options)
        : base(options)
    {
    }


    public virtual DbSet<Facultad> Facultad { get; set; }
    public virtual DbSet<Grupo> Grupo { get; set; }
    public virtual DbSet<GrupoPrograma> GrupoPrograma { get; set; }  ....

Project BLL

GrupoBLL

public class GrupoBLL: IGrupo, IDisposable
{        
    private readonly IUnitOfWork UnitOfWork;

    public GrupoBLL(IUnitOfWork UoW)
    {
        this.UnitOfWork = UoW;            
    }

    public IEnumerable<Grupo> FindAll() {

        return UnitOfWork.GrupoRepository.FindAll();
    }

    /// <summary>
    /// Dispose UnitOfWork
    /// </summary>
    public void Dispose()
    {
        UnitOfWork.Dispose();
    }
}

IGrupo

public interface IGrupo
{
    IEnumerable<Grupo> FindAll();
}

Project Api

GrupoController

public class GrupoController : ControllerBase
{

    private readonly IGrupo IGrupoBLL;
    public GrupoController(IGrupo grupo)
    {
        this.IGrupoBLL = grupo;
    }


    // GET: api/Grupo
    [HttpGet]
    [Route("All")]
    public IEnumerable<Grupo> Get()
    {
        return IGrupoBLL.FindAll();
    }

Startup

 public void ConfigureServices(IServiceCollection services)
    {   
        services.ConfigureCors();
        services.ConfigureContext(Configuration);
        services.ConfigureRepository();
        services.ConfigureAuthentication(Configuration);
        services.AddControllers();
        services.AddMvc();           
    }

ConfigureRepository

    public static class ServiceExtensions
{
    public static void ConfigureCors(this IServiceCollection services) {
        services.AddCors(c =>
        {
            c.AddPolicy("CorsAllowAll", builder => builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
            //.AllowCredentials()
            );
        });
    }

    public static void ConfigureAuthentication(this IServiceCollection services, IConfiguration Configuration)
    {

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = "uexternado.edu.co",
                    ValidAudience = "uexternado.edu.co",
                    IssuerSigningKey = new SymmetricSecurityKey(
                        Encoding.UTF8.GetBytes(Configuration["PrivateKey"])),
                    ClockSkew = TimeSpan.Zero

                });
    }

    public static void ConfigureContext(this IServiceCollection services, IConfiguration Configuration) {
        services.AddDbContext<DBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ContextProyectosInvestigacion")));
    }

    public static void ConfigureRepository(this IServiceCollection services) {
        services.AddSingleton<IUnitOfWork, UnitOfWork>();
        services.AddScoped<IGrupo, GrupoBLL>();            
        //services.AddSingleton(typeof(IRepository<>), typeof(Repository<>));
    }
}

appsettings.json

"conectionStrings": {
"ContextProyectosInvestigacion": "Server=XXXXXXX;Initial Catalog=ProyectosInvestigacion;Persist Security Info=True;User ID=XXXXX;Password=XXXXXX;"

},

I think you need to change ConfigureContext

public static void ConfigureContext(this IServiceCollection services, IConfiguration Configuration) {
    services.AddDbContext<ProyectosInvestigacionContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ContextProyectosInvestigacion")));
}

The exact issue is that you're using AddDbContext<DbContext> , when you need to specify your actual context type here, ie AddDbContext<ProyectosInvestigacionContext> . Only the exact type registration will do here.

That said, you should have absolutely none of this code. Just look at the code for your repository/UoW. Literally all you're doing is proxying to the EF context methods of virtually the same names with the same params. This is a far too common mistake and one you should nip in the bud now rather than later. The repository/UoW patterns are for low-level data access abstraction, ie things like constructing SQL queries. ORMs like EF already implement these patterns for that exact reason. The context is your UoW and each DbSet is a repository. Wrapping another repository around that doesn't abstract anything. You still have dependencies on EF, your app must still know you're using EF, and all your business logic is still leaking out, so any change to the underlying provider (EF, for example) still necessitates changes outside the repository abstraction. All you're doing here is adding something else you have to test and maintain with absolutely zero benefit.

When you use an ORM like EF, you are opting to use a third-party DAL, rather than writing your own. Writing your own DAL on top of that entirely defeats the purpose. If you want a true abstraction, look into the CQRS, service layer, or microservices patterns. Otherwise, just access your EF context directly in your controller.

In this sample project, the generic repository pattern is defined as simple and useful. CRUD operations and service integration are pretty self explanatory. You can review my friend repository.

link here

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