CRUD的通用类-使用存储库和工作单元模式在C#中进行依赖注入 [英] Generic Class for CRUD - Dependency Injection in C# using Repository and Unit Of Work Pattern

查看:89
本文介绍了CRUD的通用类-使用存储库和工作单元模式在C#中进行依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试创建一个通用存储库类,以使用依赖项注入,工作单元和存储库模式在C#中实现基本的CRUD操作。

Trying to create a Generic Repository Class for implementing basic CRUD operations in C# using dependency injection, unit of work and repository patterns.

我对这些概念很陌生。以下是我的代码。

I am very new to these concepts. Following is my code.

    public interface IUnitOfWork
    {
        IApplicationUserRepository Users { get; }

        ICompanyRepository Companies { get; }

        void Complete();
    }

  public class UnitOfWork : IUnitOfWork
    {
        private readonly ApplicationDbContext _context;
        public IApplicationUserRepository Users { get; private set; }
        public ICompanyRepository Companies { get; private set; }

        public UnitOfWork(ApplicationDbContext context)
        {
            _context = context;
            Users = new ApplicationUserRepository(context);
            Companies = new CompanyRepository(context);
        }

        public void Complete()
        {
            _context.SaveChanges();
        }
    }

 public interface IApplicationDbContext
    {
        DbSet<Company> Companies { get; set; }
        IDbSet<ApplicationUser> Users { get; set; }
        IDbSet<IdentityRole> Roles { get; set; }
    }

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
    {
        public DbSet<Company> Companies { get; set; }
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }

public abstract class GenericRepository<T> : IGenericRepository<T>
        where T : class, new()
    {
        protected GenericRepository(ApplicationDbContext context)
        {
            _dbContext = context;
        }
        private ApplicationDbContext _dbContext;


        private static IEnumerable<T> entity;

        public IEnumerable<T> Get(bool forceRefresh = false)
        {
            if (forceRefresh || entity == null)
                entity = _dbContext.Set<T>();

            return entity;
        }

        public async Task AddAsync(T entity)
        {
            _dbContext.Set<T>().Add(entity);
            await _dbContext.SaveChangesAsync();
        }

        public async Task RemoveAsync(T entity)
        {
            _dbContext.Set<T>().Remove(entity);
            await _dbContext.SaveChangesAsync();
        }
    }

在上面的代码中,我想传递IApplicationDBContext删除紧密耦合的ApplicationDBContext,但是当我使用IApplicationDbContext时,将无法访问诸如Set和SaveChanges之类的方法。我如何删除上面的依赖关系而又不丢失这些方法。我想通过构造函数传递子类存储库中的实际上下文。

In the above code I would like to pass IApplicationDBContext instead of ApplicationDBContext to remove tight coupling, but when i use IApplicationDbContext, access to methods like Set and SaveChanges is lost. How do I remove the above dependency without loosing these methods. I would like to pass the actual context from my child class repositories through constructor.

推荐答案

我认为,这应该做,你做什么想。如果将缺少的方法添加到接口,则基类(DbContext)已实现。因此,无需再次实现它。

I think, this should do, what you want. If you add the missing methods to the Interface, the base class (DbContext) has it already implemented. So no need to implement it again.

public interface IApplicationDbContext<T> where T: class
{
    //Identity Management
    IDbSet<ApplicationUser> Users { get; set; }
    IDbSet<IdentityRole> Roles { get; set; }

    //Datamanagement
    DbSet<T> DataSet { get; set; } //the Dataset of T

    DbSet<U> Set<U>() where T: class; //get other DataSets
    int SaveChanges(); //save the changes
}

然后使ApplicationDbContext泛型并将其传递给Type,您想访问那里。我只想将其与GenericRepository一起使用,那么您可能不需要接口和类上的泛型。因为那时您只需要使用已经通用的Set< U>()。

Then make the ApplicationDbContext Generic and hand it the Type, you want to access there. I fyou only want to use it with the GenericRepository, then you might not need the Generics on the Interface and the Class. Because then you just use the already generic Set<U>().

public class ApplicationDbContext<T> : IdentityDbContext<ApplicationUser>, IApplicationDbContext<T>
{
    public DbSet<T> DataSet{ get; set; }
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create<T>()
    {
        return new ApplicationDbContext<T>();
    }
}

现在,上下文是通用的并且接口具有

Now, that the context is generic and the interface has the methods, you can use the Interface in the Repository.

public abstract class GenericRepository<T> : IGenericRepository<T> where T : class, new()
{
    protected GenericRepository(IApplicationDbContext<T> context)
    {
        _dbContext = context;
    }
    private TApplicationDbContext<T> _dbContext;


    private static IEnumerable<T> entity;

    public IEnumerable<T> Get(bool forceRefresh = false)
    {
        if (forceRefresh || entity == null)
            entity = _dbContext.Set<T>();

        return entity;
    }

    public async Task AddAsync(T entity)
    {
        _dbContext.Set<T>().Add(entity);
        await _dbContext.SaveChangesAsync();
    }

    public async Task RemoveAsync(T entity)
    {
        _dbContext.Set<T>().Remove(entity);
        await _dbContext.SaveChangesAsync();
    }
}

如果您不使用默认数据集并且仅将其与存储库一起使用,您可以在接口和上下文上省略泛型。

If you don't use the "default dataset" and only use it with the repository, you can ommit the Generics on the interface and the context.

public interface IApplicationDbContext
{
    //Identity Management
    IDbSet<ApplicationUser> Users { get; set; }
    IDbSet<IdentityRole> Roles { get; set; }

    DbSet<U> Set<U>() where T: class; //get DataSets
    int SaveChanges(); //save the changes
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

public abstract class GenericRepository<T> : IGenericRepository<T> where T : class, new()
{

    protected GenericRepository(IApplicationDbContext context)
    {
        _dbContext = context;
    }
    private IApplicationDbContext _dbContext;


    private static IEnumerable<T> entity;

    public IEnumerable<T> Get(bool forceRefresh = false)
    {
        if (forceRefresh || entity == null)
            entity = _dbContext.Set<T>();

        return entity;
    }

    public async Task AddAsync(T entity)
    {
        _dbContext.Set<T>().Add(entity);
        await _dbContext.SaveChangesAsync();
    }

    public async Task RemoveAsync(T entity)
    {
        _dbContext.Set<T>().Remove(entity);
        await _dbContext.SaveChangesAsync();
    }
}

当然,如果您真的喜欢通用接口和上下文,可以在存储库中使用DataSet属性代替.Set< T>()。

And of course, if you really like the generic Interface and Context, you can use the DataSet Property in the Repository instead of .Set<T>().

这篇关于CRUD的通用类-使用存储库和工作单元模式在C#中进行依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆