Внедрение зависимостей в службу БД

#class #dependency-injection #entity-framework-core #blazor-server-side

Вопрос:

У меня проблема с ДИ. У меня есть пользовательский класс, который должен импортировать некоторые данные в базу данных через службу. Если я использую эту службу в компоненте Blazor, она хорошо работает с @injection.

Но я не могу использовать его в своем пользовательском классе. Я пробовал это так

 public class ImportXml
{
    private readonly AccountService _accountService;

    public ImportXml(AccountService accountService)
    {
        _accountService = accountService;
    }

     public ImportXml(List<Transaction> transactions, Account account)
    {
        if(account.Transactions==null)
        {
            account.Transactions = new List<Transaction>();
        }

        account.Transactions.AddRange(transactions);
    
        _accountService.UpdateAccountsAsync(account);
           
    }
}
 

В startup.cs сервис зарегистрирован таким образом.

 services.AddScoped<AccountService>();
 

Если я вызову ImportXML _accountService, значение будет равно нулю.

Мой текущий обходной путь заключается в том, чтобы просто отправить службу как часть параметров. Но я хотел бы иметь рабочее решение с DI.

     public class ImportXml
    {
    public ImportXml(List<Transaction> transactions, Account account, AccountService accountService)
    {
        if(account.Transactions==null)
        {
            account.Transactions = new List<Transaction>();
        }
        
        account.Transactions.AddRange(transactions);
                 
        accountService.UpdateAccountsAsync(account);
           
    }
    }
 

Большое спасибо

Ответ №1:

У вас здесь есть пара проблем.

  1. Для того, чтобы ImportXML получал учетную запись через DI, ImportXML также должен быть предоставлен контейнером DI.
  2. Вы используете второй конструктор, чтобы попытаться выполнить действие, а не метод. Конструкторы следует просто использовать для настройки класса, а не для выполнения каких-либо действий, особенно длительных действий, таких как обновление базы данных. Кроме того, обратите внимание, что конструктор не является асинхронным.

Измените свой класс ImportXML

 public class ImportXml
{
    private readonly AccountService _accountService;

    // This it the constructor, so just set the object up
    public ImportXml(AccountService accountService)
    {
        _accountService = accountService;
    }

    // This is the method to perform the update
    public async Task DoAccountUpdateAsync(
        List<Transaction> transactions, 
        Account account)
    {
        if(account.Transactions==null)
        {
            account.Transactions = new List<Transaction>();
        }

        account.Transactions.AddRange(transactions);
    
        await _accountService.UpdateAccountsAsync(account);
    }
}
 

Зарегистрируйте как AccountService, так и ImportXML

 services.AddScoped<AccountService>();
services.AddScoped<ImportXml>();
 

Из клиента введите ImportXML и используйте эту службу.
Когда ImportXML вводится, его параметры конструктора (AccountService) будут автоматически предоставлены DI и введены в ImportXML.

 @inject ImportXML ImportXML

<button @onclick=@HandleClick>Perform Account Update</button>

@code {
    List<Transactions> _transactionsForMethod;
    Account _accountForMethod;

    async Task HandleClick()
    {
        await ImportXML.DoAccountUpdateAsync(
            _transactionsForMethod,
            _accoountForMethod);
    }
}
 

Комментарии:

1. Спасибо за совет, я его проверю.