【问题标题】:Using Inheritance vs Dependency injection with generic Repository in ASP.NET Core在 ASP.NET Core 中使用带有通用存储库的继承与依赖注入
【发布时间】:2022-01-06 10:18:35
【问题描述】:

考虑以下通用Repository 接口及其实现:

public interface IRepository<T>
{
    IQueryable<T> FindAll(List<string> includes = null);

    void Add(T entity);

    void Update(T entity);

    void Remove(T entity);
}

public class Repository<T> : IRepository<T> where T : class
{
    protected DatabaseContext _dbContext { get; set; }

    protected ILogger<Repository<T>> _logger { get; set; }
    
    public Repository(DatabaseContext dbContext, ILogger<Repository<T>> logger)
    {
        _logger = logger;
        _dbContext = dbContext;
    }

    public IQueryable<T> FindAll(List<string> includes = null)
    {
        try
        {
            IQueryable<T> items = _dbContext.Set<T>().AsNoTracking();

            if (includes != null && includes.Any())
            {
                includes.Where(i => i != null).ToList().ForEach(i => { items = items.Include(i); });
            }

            return items;
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} FindAll function error", typeof(Repository<T>));
            return null;
        }
    }

    public void Add(T entity)
    {
        try
        {
            _dbContext.Set<T>().Add(entity);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} Add function error", typeof(Repository<T>));
        }
    }

    public void Update(T entity)
    {
        try
        {
            _dbContext.Set<T>().Update(entity);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} Update function error", typeof(Repository<T>));
        }
    }

    public void Remove(T entity)
    {
        try
        {
            _dbContext.Set<T>().Remove(entity);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} Remove function error", typeof(Repository<T>));
        }
    }
}

为了将它与 User 这样的数据库实体一起使用,我有两个选择。

要么从通用 Repository 继承 UserRepository 实现:

public class UserRepository : Repository
{
    public UserRepository(MyDbContext context) : base(context)
    {
    }
}

或在UserRepository 实现中创建通用IRepository 接口的实例并使用依赖注入:

public class UserRepository : IUserRepository
{
    private readonly IRepository _repo;

    public UserRepository(IRepository repo)
    {
        _repo = repo;
    }
}

根据我在 ASP.NET Core 中存储库模式的有限经验,我可以使用其中任何一种并在使用数据库的 CRUD 应用程序中获得相同的结果。

我的问题是,在哪种情况下应该使用哪一个?

更新:

我仍然可以使用继承方法创建和注入IUserRepository

public partial interface IUserRepository : IRepository
{
}

public class UserRepository : Repository, IUserRepository
{
    public UserRepository(MyDbContext context) : base(context)
    {
    }
}

【问题讨论】:

标签: c# asp.net-core inheritance dependency-injection repository-pattern


【解决方案1】:

我不禁注意到IRepository 丢失了它的遗传参数。

这里要问的问题是,通过在存储库中注入 IRepository 可以获得什么。在您的应用程序生命周期中是否会有多个IRepository 实现?

您在这里的抽象是存储库本身,这就是需要注入的东西,而不是 IRepository 本身,我看不出有任何理由拥有多个或替代实现。

正如 Dai 在 cmets 中提到的,你根本不应该使用它。通用存储库对 EF 没有意义,有些人认为根本没有意义。

【讨论】:

  • 感谢您的回答。我不是这种模式的专家,只是试图理解它,因为我已经看到它以上述两种方式使用。所以,如果我理解正确,你提出了两点。我应该直接在我的控制器/服务 (a) 中使用 Repository,或者我不应该完全使用它,而是直接在我的控制器/服务 (b) 中使用 DbContext。对吗?
  • 请原谅我的无知,但写Repository 的一个原因是不公开ORM 框架在控制器中的使用。如果我想更改 ORM,我只需要更改存储库实现而不是控制器/服务中的代码。请对此有所了解。
  • 当然,在您的情况下就是 IUserRepository。 IRepository 本身是我不理解的抽象。尤其是没有泛型参数。
猜你喜欢
  • 1970-01-01
  • 2021-11-05
  • 2015-09-03
  • 2018-05-02
  • 2019-12-21
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多