在 ASP.Net Core 上从 UnitOfWork 模式中的上下文构建

Build from context in UnitOfWork pattern on ASP.Net Core

我在 ASP.Net MVC 项目中有一个存储库和 UnitOfWork 模式,现在我想将其移动到我的 ASP.Net 核心项目中,该项目在 UnitOfWork class.[=18= 中获取上下文]

上下文 class :

public class LoginContext:DbContext
{

    public LoginContext(DbContextOptions<LoginContext> options)
        : base(options)
    {

    }
    public DbSet<Person> People { get; set; }
    <..other classes..>
}

通用存储库:

public class GenericRepository<TEntity> where TEntity : class
{
    private LoginContext _context;
    private DbSet<TEntity> _entityTable;

    public GenericRepository(LoginContext context)
    {
       _context = context;
       _entityTable = context.Set<TEntity>();
    }

    public virtual async Task<TEntity> GetInfo(int id)
    {
       return await _entityTable.FindAsync(id);
    }

    <... Other Methods ...>

UnitOfWork

public class AccountProvider : IUnitOfWork
{
    private readonly LoginContext loginContext;

    private GenericRepository<Person> personRepository;

    <... and Others ...>
}

此外,我的 appsettings.json 中有 connectionString :

"ConnectionStrings": {
"LoginContext": "Server=.\MYSQLSERVER;Database=<DatabaseName>;Integrated Security=True;Trusted_Connection=True;"}

startup.cs 中的 ConfigureServices 方法 :

services.AddDbContext<LoginContext>(options => options.UseSqlServer(Configuration.GetConnectionString("LoginContext")));

现在在控制器中,我得到了 AccountProvider(UnitOfWork) 的实例并想使用它:

[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
    private readonly AccountProvider _accountProvider;

    public LoginController(AccountProvider account)
    {
        _accountProvider = account;
    }
    <... methods ...>
}

当我 运行 投影并向控制器发送请求时,我得到这样的异常:

InvalidOperationException: Unable to resolve service for type 'DataLogin.Context.AccountProvider' while attempting to activate 'MyProject.Controllers.LoginController'

我知道问题是在控制器中获取上下文,并尝试在 Internet 上查看 .Net 中的 UnitOfWork 模式 Core.But 不了解获取的正确方法 that.Please 指导我。 .

解决您的问题:

You're not registering the AccountProvider (most likely).

您看到的错误基本上意味着编译器发现您正在尝试将 AccountProvider 作为服务使用,但您忘记在启动时注册它。

// In startup.cs register a scoped AccountProvider as the concrete class for IUnitOfWork:
services.AddScoped<IUnitOfWork, AccountProvider>()

这将解决您的错误。但是通过查看您的代码,我可以看到一些设计缺陷。 您缺少通用存储库的接口。

没有使用接口的问题:

By not using an IGerericRepository interface you are tightly coupling your Repository to your UnitOfWork class. By doing so, your UnitOfWork class will become almost impossible to test.

我的建议是创建 IRepository class 并在您的 UnitOfWork 中使用它。

public interface IRepository<TEntity> where TEntity : class
{
    // Code omitted for brevity.
}

public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    // Code omitted for brevity.
}

public class AccountProvider : IUnitOfWork 
{
    private LoginContext _context;

    // Use the IRepository class
    private IRepository<Person> _personRepository;

    public AccountProvider(LoginContext context) 
    {
        _context = context;
    }

    // Initiate like this
    public IRepository<Person> PersonRepository 
    {
        get
        {
            if (_personRepository == null)
            {
                _personRepository = new GenericRepository<Person>(_context);
            }
            return _personRepository;
        }
    }
}

Then there's the problem in your naming of the UnitOfWork class.

UnitOfWork class 应该保存您的应用程序可以使用的每个可能的数据库上下文。您唯一会在控制器中调用的是您的 UnitOfWork class.

意思是通过将其称为 AccountProvider,您是在暗示这个具体 class 所做的唯一事情就是与帐户相关的操作。这几乎没有意义,因为 99% 的时间你的应用程序将更多的数据保存到数据库中,而不仅仅是帐户。所以我建议您将其重命名为 UnitOfWorkDataAccessLayer.