如何在存储库中注入 IServiceProvider 来实现工作单元模式?

How to implement unit of work pattern with IServiceProvider injected in repositories?

我必须在我的项目中实现工作单元模式,但我找不到使用内存数据库执行此操作的正确方法。我有两个存储库:

public class RepositoryA : IRepositoryA
{
    private readonly IServiceScope _scope;
    private readonly ApiContext _apiContext;

    public RepositoryA(IServiceProvider services)
    {
        _scope = services.CreateScope();
        _apiContext = _scope.ServiceProvider.GetRequiredService<ApiContext>();
    }

    //some methods
}

public class RepositoryB : IRepositoryB
{
    private readonly IServiceScope _scope;
    private readonly ApiContext _apiContext;

    public RepositoryB(IServiceProvider services)
    {
        _scope = services.CreateScope();
        _apiContext = _scope.ServiceProvider.GetRequiredService<ApiContext>();
    }

    //some methods
}

我发现了一些在其他项目中工作的工作单元模式的好例子。

public interface IUnitOfWork
{
   public IRepositoryA IRepositoryA { get; }
   public IRepositoryB IRepositoryB { get; }

   void SaveChanges();
}

 public class UnitOfWork : IUnitOfWork
    {
        private ApiContext _apiContext;
        private IRepositoryA _repositoryA ;
        private IRepositoryB _repositoryB ;

        public UnitOfWork(ApiContext apiContext)
        {
            _apiContext = apiContext;
        }

        public IRepositoryA RepositoryA 
        {
            get
            {
                if(_repositoryA == null)
                {
                    _repositoryA = new RepositoryA(_apiContext);
                }
                return _repositoryA ;
            }
        }

       public IRepositoryB RepositoryB 
        {
            get
            {
                if(_repositoryB == null)
                {
                    _repositoryB = new RepositoryB(_apiContext);
                }
                return _repositoryB;
            }
        }

        public void SaveChanges()
        {
            _apiContext.SaveChangesAsync();
        }
    }

在我的 Startup.cs 我的 ConfigureServices 方法中有这个:

services.AddSingleton<IUnitOfWork, UnitOfWork>();
services.AddSingleton<IRepositoryA, RepositoryA>();
services.AddSingleton<IRepositoryB, RepositoryB>();
services.AddDbContext<ApiContext>(options => options.UseInMemoryDatabase("Database"));

在此示例中,工作单元试图将 apiContext 传递给存储库构造函数。我不能这样做,因为两个存储库都不期望构造函数中的 apiContext,而是 IServiceProvider。当我尝试像这样创建我的存储库时:

public RepositoryA(ApiContext apiContext)
{
    _apiContext = apiContext;
}

我收到一个错误:

InvalidOperationException: 无法从单例 Project.Repositories.Interface.IRepositoryA.

使用作用域服务 Project.Data.ApiContext'

这个错误是因为内存数据库。所以我需要在存储库的构造函数中注入 IServiceProvider 并创建范围,这是在没有工作单元的情况下工作的。但是现在我需要工作单元,但我不知道如何实现它。有什么方法可以以不同的方式实现工作单元,或者更改我的存储库?

如错误所示,您不应将范围内的生命周期依赖项注入单例。 DbContexts 通常注册为作用域。

如果存储库依赖于上下文,那么它们也应该被限定范围。

例如

services.AddScope<IUnitOfWork, UnitOfWork>(); 
services.AddScope<IRepositoryA, RepositoryA>(); 
services.AddScope<IRepositoryB, RepositoryB>();
services.AddDbContext<ApiContext>(options => options.UseInMemoryDatabase("Database"));