Сборка из контекста в шаблоне UnitOfWork на ASP.Net Core - PullRequest
0 голосов
/ 19 октября 2019

У меня был шаблон Repository и UnitOfWork в проекте ASP.Net MVC, и теперь я хочу переместить его в мой проект ASP.Net Core, который получает контекст в классе UnitOfWork.

Класс контекста:

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 ...>
}

Кроме того, у меня есть connectionString в моем appsettings.json :

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

и метод ConfigureServices в startup.cs :

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: Невозможно выполнитьразрешить службу для типа «DataLogin.Context.AccountProvider» при попытке активировать «MyProject.Controllers.LoginController»

Я знаю, что проблема заключается в получении контекста в контроллере, и попробуйте просмотреть Интернет дляШаблон UnitOfWork в .Net Core. Но неПожалуйста, ведите меня ..

1 Ответ

2 голосов
/ 19 октября 2019

Чтобы решить вашу проблему:

Вы не регистрируете AccountProvider (скорее всего).

Эта ошибка, которую вы видите, в основном означает, что компилятор видит васВы пытаетесь использовать AccountProvider в качестве службы, но вы забыли зарегистрировать его при запуске.

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

Это исправит вашу ошибку. Но, просматривая ваш код, я вижу некоторые недостатки дизайна. Вам не хватает интерфейса для вашего общего хранилища.

Проблема неиспользования интерфейсов:

Не используя интерфейс IGerericRepository, вы тесно связываете свой Repository с вашим классом UnitOfWork. Таким образом, ваш класс UnitOfWork станет практически невозможным для тестирования.

Мой совет будет создать класс IRepository и использовать его в вашем 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;
        }
    }
}

Тогда в названии класса UnitOfWork есть проблема.

Класс UnitOfWork должен содержать каждый возможный контекст базы данных, который может использовать ваше приложение. Единственное, что вы когда-либо будете вызывать в контроллерах, это ваш класс UnitOfWork.

То есть, называя его AccountProvider, вы предполагаете, что этот конкретный класс выполняет только действия, связанные с учетной записью. Это не имеет особого смысла, поскольку в 99% случаев ваше приложение хранит в базе данных гораздо больше данных, чем просто учетные записи. Поэтому я предлагаю вам переименовать это что-то вроде UnitOfWork или DataAccessLayer.

...