ASP .NET Core MVC - CRUD básico com ADO .NET - I

 Neste artigo eu vou mostrar como fazer um CRUD básico usando ADO .NET em aplicações ASP .NET Core MVC.

Posso usar ADO .NET com .NET Core sem usar o Entity Framework Core ?

Pode, e , neste artigo vou mostrar um exemplo prático bem simples de como usar ADO .NET com .NET Core, em uma aplicação ASP .NET Core MVC e realizar o CRUD básico.

Neste artigo eu vou usar o Visual Studio 2017 Community update 15.4 e o SQL Server 2012 Express.

Como exemplo vamos usar um banco de dados chamado CadastroDB e a tabela Funcionarios que tem a seguinte estrutura e dados:

O script SQL para gerar a tabela é o seguinte:

USE [CadastroDB]
CREATE TABLE [dbo].[Funcionarios](
	[FuncionarioId] [int] IDENTITY(1,1) NOT NULL,
	[Nome] [nvarchar](80) NOT NULL,
	[Cidade] [nvarchar](50) NOT NULL,
	[Departamento] [nvarchar](50) NULL,
	[Sexo] [nvarchar](10) NOT NULL
)

Assim vamos acessar o banco de dados existente realizando o CRUD.

Recursos usados:

Criando o projeto no VS 2017

Abra o VS 2017 Community e crie um novo projeto ASP .NET Core usando o template Web Application(Model-View-Controller).

  • Create New Project;
  • Visual C# -> .NET Core -> ASP .NET Core Web Application;
  • Informe o nome AspCore_Crud

  • Clique em OK e a seguir selecione o template Web Application(Model-View-Controller) , marque ASP .NET Core 2.1(ou ASP .NET Core 2.0);

A o clicar no botão OK teremos o projeto criado com a estrutura abaixo:

Vemos a estrutura do projeto contendo as referências  e as pastas Controllers, Models e Views bem como os arquivos Startup e appsettings.json.

Vamos usar esses recursos para criar nossa aplicação
ASP .NET Core MVC.

Já temos então as referências para System.Data, System.Data.SqlClient e as demais referências necessárias para usar a ADO .NET e Data Annotations no projeto.

Criando a classe de dominio

Vamos criar a classe Funcionario na pasta Models que vai representar o nosso modelo de domínio e será usada para acessar e gerenciar informações dos funcionários no banco de dados.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ApnCore_Crud.Models
{
    [Table("Funcionarios")]
    public class Funcionario
    {
        [Key]
        public int FuncionarioId { get; set; }
        [Required]
        public string Nome { get; set; }
        [Required]
        public string Cidade { get; set; }
        public string Departamento { get; set; }
        [Required]
        public string Sexo { get; set; }
    }
}

Aplicamos alguns atributos Data Annotations na definição da entidade Funcionario para mapear para tabela Funcionarios.

Criando a camada de acesso a dados com ADO .NET

Para criar a camada de acesso a dados poderiamos criar um novo projeto do tipo Class Library mas neste artigo, para simplificar, eu vou definir as classes da camada de acesso a dados na pasta Models do projeto. Em um projeto maior o indicado seria criar um novo projeto para fazer isso.

Vamos criar uma interface chamada IFuncionarioDAL na pasta Models com o código abaixo:

using System.Collections.Generic;
namespace ApnCore_Crud.Models
{
    interface IFuncionarioDAL
    {
        IEnumerable<Funcionario> GetAllFuncionarios();
        void AddFuncionario(Funcionario funcionario);
        void UpdateFuncionario(Funcionario funcionario);
        Funcionario GetFuncionario(int? id);
        void DeleteFuncionario(int? id);
    }
}

Nesta interface eu defini os métodos básicos para realizar o CRUD e consultar informações de funcionários:

Vamos agora criar a classe FuncionarioDAL que implementa esta interface:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
namespace ApnCore_Crud.Models
{
    public class FuncionarioDAL : IFuncionarioDAL
    {
        string connectionString = @"Data Source=MACORATTI;Initial Catalog=CadastroDB;Integrated Security=True;"; 
        public IEnumerable<Funcionario> GetAllFuncionarios()
        {
            List<Funcionario> lstfuncionario = new List<Funcionario>();
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                SqlCommand cmd = new SqlCommand("SELECT FuncionarioId, Nome,Cidade, Departamento,Sexo from Funcionarios", con);
                cmd.CommandType = CommandType.Text;
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    Funcionario funcionario = new Funcionario();
                    funcionario.FuncionarioId = Convert.ToInt32(rdr["FuncionarioId"]);
                    funcionario.Nome = rdr["Nome"].ToString();
                    funcionario.Cidade = rdr["Cidade"].ToString();
                    funcionario.Departamento = rdr["Departamento"].ToString();
                    funcionario.Sexo = rdr["Sexo"].ToString();
                    lstfuncionario.Add(funcionario);
                }
                con.Close();
            }
            return lstfuncionario;
        }
        public void AddFuncionario(Funcionario funcionario)
        {
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                string comandoSQL ="Insert into Funcionarios (Nome,Cidade,Departamento,Sexo) 
                                                        Values(@Nome, @Cidade, @Departamento, @Sexo)";
                SqlCommand cmd = new SqlCommand(comandoSQL, con);
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.AddWithValue("@Nome", funcionario.Nome);
                cmd.Parameters.AddWithValue("@Cidade", funcionario.Cidade);
                cmd.Parameters.AddWithValue("@Departamento", funcionario.Departamento);
                cmd.Parameters.AddWithValue("@Sexo", funcionario.Sexo);
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();
            }
        }
        public void UpdateFuncionario(Funcionario funcionario)
        {
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                string comandoSQL = "Update Funcionarios set Nome = @Nome, Cidade = @Cidade, Departamento = 
                                                              @Departamento, Sexo = @Sexo where FuncionarioId = @FuncionarioId";
                SqlCommand cmd = new SqlCommand(comandoSQL, con);
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.AddWithValue("@FuncionarioId", funcionario.FuncionarioId);
                cmd.Parameters.AddWithValue("@Nome", funcionario.Nome);
                cmd.Parameters.AddWithValue("@Cidade", funcionario.Cidade);
                cmd.Parameters.AddWithValue("@Departamento", funcionario.Departamento);
                cmd.Parameters.AddWithValue("@Sexo", funcionario.Sexo);
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();
            }
        }
        public Funcionario GetFuncionario(int? id)
        {
            Funcionario funcionario = new Funcionario();
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                string sqlQuery = "SELECT * FROM Funcionarios WHERE FuncionarioId= " + id;
                SqlCommand cmd = new SqlCommand(sqlQuery, con);
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    funcionario.FuncionarioId = Convert.ToInt32(rdr["FuncionarioId"]);
                    funcionario.Nome = rdr["Nome"].ToString();
                    funcionario.Cidade = rdr["Cidade"].ToString();
                    funcionario.Departamento = rdr["Departamento"].ToString();
                    funcionario.Sexo = rdr["Sexo"].ToString();
                }
            }
            return funcionario;
        }
        public void DeleteFuncionario(int? id)
        {
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                string comandoSQL = "Delete from Funcionarios where FuncionarioId = @FuncionarioId";
                SqlCommand cmd = new SqlCommand(comandoSQL, con);
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.AddWithValue("@FuncionarioId", id);
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();
            }
        }
    }
}

Neste código temos a implementação da nossa camada de acesso a dados usando ADO .NET. O código esta bem simplificado para facilitar o entendimento.

Eu vou sugerir algumas melhorias que você pode fazer neste código:

  • Definir a string de conexão em um arquivo de configuração e não fixa no código como fizemos aqui;
  • Utilizar stored procedures ao invés de consultas texto;
  • Definir um tratamento de erros;
  • Usar blocos using para evitar ficar repetindo a abertura e fechamento da conexão;

Em todo o caso o objetivo era mostrar a utilzação da ADO .NET no .NET Core, e, isso esta sendo feito.

Registrando a interface e classe de acesso a dados como um serviço

Para poder usar o recurso nativo do contâiner de injeção de dependência da ASP .NET Core vamos registrar a interface e a sua implementação no método ConfigureServices() da classe Startup:

    public void ConfigureServices(IServiceCollection services)
    {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            //cria a cada solicitação
            services.AddTransient<IFuncionarioDAL, FuncionarioDAL>();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
   }   

O método ConfigureServices() é responsável por definir os serviços que a aplicação vai usar, incluindo recursos da plataforma como ASP .NET Core MVC e Entity Framework.

Na implementação da Injeção de dependência do ASP.NET Core, vemos o conceito de lifetimes ou "tempo de vidas". Um lifetime ou tempo de vida especifica quando um objeto DI-injetado é criado ou recriado. Existem três possibilidades:

  1. - Transient : Criado a cada vez que são solicitados.
  2. - Scoped: Criado uma vez por solicitação.
  3. - Singleton: Criado na primeira vez que são solicitados. Cada solicitação subseqüente usa a instância que foi criada na primeira vez.

O parâmetro IServiceCollection permite configurar diferentes tipos de serviços, seja por criação de objeto ou correspondência a uma interface específica, e suporta os lifetimes mencionados.

No nosso exemplo usamos o lifetime Transient e informando que quando tivermos uma referência a uma instância da interface queremos que seja injetado a instância da classe concreta.

Fazendo assim podemos injetar o serviço no Controller da nossa aplicação.

Criando o Controlador FuncionarioController

Vamos criar o controller FuncionarioController na pasta Controllers e definir os métodos Action para consumir a nossa camada de acesso a dados.

Para isso vamos usar o recurso da injeção de dependência no construtor do controlador injetando a classe da nossa camada de acesso a dados.

Clique com o botão direito sobre a pasta Controllers e a seguir clique em Add->Controller;

Na janela do Scaffolding selecione a opção MVC Controller - Empty e clique em Add;

Agora informe o nome FuncionarioController e clique em Add;

Inclua o código abaixo neste controlador:

using ApnCore_Crud.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
namespace ApnCore_Crud.Controllers
{
    public class FuncionarioController : Controller
    {
        private readonly IFuncionarioDAL funci;
        public FuncionarioController(IFuncionarioDAL funcionario)
        {
            funci = funcionario;
        }
        public IActionResult Index()
        {
            List<Funcionario> listaFuncionarios = new List<Funcionario>();
            listaFuncionarios = funci.GetAllFuncionarios().ToList();
            return View(listaFuncionarios);
        }
        [HttpGet]
        public IActionResult Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            Funcionario funcionario = funci.GetFuncionario(id);
            if (funcionario == null)
            {
                return NotFound();
            }
            return View(funcionario);
        }
        [HttpGet]
        public IActionResult Create()
        {
            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create([Bind] Funcionario funcionario)
        {
            if (ModelState.IsValid)
            {
                funci.AddFuncionario(funcionario);
                return RedirectToAction("Index");
            }
            return View(funcionario);
        }
        [HttpGet]
        public IActionResult Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            Funcionario funcionario = funci.GetFuncionario(id);
            if (funcionario == null)
            {
                return NotFound();
            }
            return View(funcionario);
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Edit(int id, [Bind]Funcionario funcionario)
        {
            if (id != funcionario.FuncionarioId)
            {
                return NotFound();
            }
            if (ModelState.IsValid)
            {
                funci.UpdateFuncionario(funcionario);
                return RedirectToAction("Index");
            }
            return View(funcionario);
        }
        [HttpGet]
        public IActionResult Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            Funcionario funcionario = funci.GetFuncionario(id);
            if (funcionario == null)
            {
                return NotFound();
            }
            return View(funcionario);
        }
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public IActionResult DeleteConfirmed(int? id)
        {
            funci.DeleteFuncionario(id);
            return RedirectToAction("Index");
        }
    }
}

Neste código injetamos o serviço da camada de acesso a dados no construtor do controlador e definimos os métodos para criar, atualizar e excluir dados de funcionários usando a instância do serviço.

Na próxima parte do artigo vamos criar as Views do projeto.

'Porque há um só Deus, e um só Mediador entre Deus e os homens, Jesus Cristo homem.'
1 Timóteo 2:5

 

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti