ASP .NET Core - Implementando a Onion Architecture - V


Neste artigo vamos criar uma aplicação ASP .NET Core WEBAPI fazendo uma implementação básica da arquitetura em Cebola ou Onion Architecture.

Continuando a quarta parte do artigo vamos iniciar a implementação do projeto eStore.Shared da camada Infrastructure.

Implementação do projeto eStore.Shared

No projeto eStore.Shared vamos criar o método de extensão AddInfrastructure para a interface IServiceCollection e usar um parâmetro do tipo IConfiguration.

Estamos usando uma estratégia para dividir os registros dos nossos serviços criando um método de extensão na camada de infraestrutura para poder usar este método na camada de apresentação onde vamos precisar usar os serviços de repositório. Assim podemos dividir nossos registros de serviços de acordo com vários critérios, como por exemplo:

ConfigurationServices => métodos que recuperam informações de uma seção de configuração específica;
BusinessServices => Todos os registros de serviços comerciais;
RepositoryServices => Todos os registros de serviço de repositório;

Em outras palavras, você pode dividir os registros de serviço como quiser de acordo com o seu negócio.

Abra o projeto Shared e crie a classe DependencyInjection como uma classe estática e defina a seguir o método de extensão AddInfrastructure() nesta classe:

1- DependencyInjection

using eStore.Application.Interfaces;
using eStore.Application.Services;
using eStore.Domain.Interfaces;
using eStore.Persistence.Context;
using eStore.Persistence.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace eStore.Shared
{
    public static class DependencyInjection
    {
        public static IServiceCollection AddInfrastructure(this IServiceCollection services,
            IConfiguration configuration)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    configuration.GetConnectionString("DefaultConnection"),
                    b => b.MigrationsAssembly(typeof(ApplicationDbContext)
                            .Assembly.FullName)));

            services.AddScoped<IProductRepository, ProductRepository>();
            services.AddScoped<ICategoryRepository, CategoryRepository>();
            services.AddScoped<IProductService, ProductService>();
            services.AddScoped<ICategoryService, CategoryService>();


            return services;
        }
    }
}

Neste código estamos :

- Registrando o contexto como um serviço e definindo as opções para DbContext como o provedor do banco de dados e a string de conexão definida no arquivo appsettings.json

- Usando o método MigrationsAssembly() para definir o assembly onde as migrações serão mantidas para o contexto do assembly definido onde esta a classe de contexto ApplicationDbContext

- Registrando os serviços para os repositórios definidos nesta camada e os serviços definidos na camada Application;

Com isso já podemos aplicar o recurso Migrations para poder gerar o banco de dados e as tabelas que nossa aplicação irá usar conforme a definição feita no arquivo de contexto.

Só precisamos definir a string de conexão e como vamos usar esses serviços na camada API da nossa aplicação vamos aproveitar o arquivo appsettings.json já existente neste projeto e definir a string de conexão conforme abaixo:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=DESKTOP\\SQLEXPRESS;Initial Catalog=eStoreDatabase;Integrated Security=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Importante destacar que você deve usar a string de conexão da instância do seu SQL Server local.

Agora podemos aplicar o Migrations em nossa aplicação.

Para isso abra uma janela no Package Manager Console e defina a opção Default project como sendo o projeto infrastructure\eStore.Persistente que é onde esta o nosso arquivo de contexto e digite :  add-migration inicial

Este comando irá criar o arquivo de script contendo os comandos para criar o banco de dados e as tabelas Categories e Products.

Você pode conferir que foi criada a pasta Migrations no projeto Persistence e nesta pasta temos o arquivo de script xxxxxxxx_inicial.cs e o arquivo ApplicationDbContextModelSnapshot :

Para aplicar estes comandos digite na janela Package Manager Console o comando:  update-database

Após a execução do comando abra o Server Explorer no menu View do Visual Studio podemos conferir o banco de dados eStoreDatabase criado e as tabelas Categories e Products e também os dados que foram incluídos na tabela Categories conforme mostrado a seguir:

Vamos aproveitar e incluir alguns dados na tabela Products. Vamos fazer isso criando uma migração vazia e definindo os comandos SQL nos métodos Up() e Down() do arquivo criado.

Abra novamente a janela do Package Manager Console e defina a opção Default project como sendo o projeto infrastructure\eStore.Persistente que é onde esta o nosso arquivo de contexto e digite :  add-migration SeedProducts

Este comando vai criar o arquivo SeedProducts na pasta Migrations vazio contendo apenas os métodos Up() e Down().

Abro arquivo SeedProducts e inclua o código abaixo :

using Microsoft.EntityFrameworkCore.Migrations;

namespace eStore.Persistence.Migrations
{
    public partial class SeedProducts : Migration
    {
        protected override void Up(MigrationBuilder mb)
        {
            mb.Sql("INSERT INTO Products(Name,Description,Price,Stock,CategoryId) " +
            "VALUES('Caderno espiral','Caderno espiral 100 fôlhas',7.45,50,1)");

            mb.Sql("INSERT INTO Products(Name,Description,Price,Stock,CategoryId) " +
            "VALUES('Estojo escolar','Estojo escolar cinza',5.65,70,1)");

            mb.Sql("INSERT INTO Products(Name,Description,Price,Stock,CategoryId) " +
            "VALUES('Borracha escolar','Borracha branca pequena',3.25,80,1)");

            mb.Sql("INSERT INTO Products(Name,Description,Price,Stock,CategoryId) " +
            "VALUES('Calculadora escolar','Calculadora simples',15.39,20,2)");

        }
        protected override void Down(MigrationBuilder mb)
        {
            mb.Sql("DELETE FROM Products");
        }
    }
}

No método Up() usamos o método Sql da classe MigrationBuilder e incluímos a instrução SQL usando o comando INSERT INTO para incluir produtos na tabela, e,  no método Down() usamos o comando SQL DELETE FROM.

Para aplicar estes comandos digite na janela Package Manager Console o comando:  update-database

A seguir verifique a tabela Products com os dados no Server Explorer:

Agora já temos dados nas tabelas Categories e Products e já podemos iniciar a implementação da camada de apresentação representada pela camada eStore.API.

Na próxima parte do artigo vamos definir a camada de apresentação : a API.

"Melhor é o que tarda em irar-se do que o poderoso, e o que controla o seu ânimo do que aquele que toma uma cidade."
Provérbios 16:32

Referências:


José Carlos Macoratti