Back-End

19 jan, 2016

Curso Entity Framework – CRUD com Stored Procedures

Publicidade

Neste artigo vou mostrar como podemos realizar as operações CRUD (Create, Read, Update, Delete) usando stored procedures com o Entity Framework (para ver os artigos anteriores, acesse aqui).

O Entity Framework possui a habilidade de automaticamente construir nativamente comandos para o banco de dados baseado em suas consultas LINQ to Entities ou Entity SQL, bem como construir os comandos para incluir, atualizar ou deletar dados. No entanto, você pode querer sobrescrever esses passos e usar suas stores procedures pré-definidas.

Na aula anterior vimos como obter dados usando uma stored procedure e neste artigo vamos usá-las para realizar as operações para criar, atualizar e deletar (CUD) registros do banco de dados usando o DbContext. Isso significa que o contexto irá executar as stored procedures ao invés de comandos DDL, usando o comando context.SaveChanges().

Para esta aula vamos criar as seguintes stored procedures:

  1. sp_InserirAluno: que inclui um novo aluno no banco de dados;
  2. sp_AtualizarAluno: que atualiza um aluno existente no banco de dados;
  3. sp_DeletaAluno: que deleta um aluno no banco de dados;

Vamos, então, criar essas stored procedures no banco de dados EscolaDB.mdf criado no segundo artigo desta série.

Abra o banco de dados e clique com o botão direito sobre o item Stored Procedures e, a seguir, em New Stored Procedure.

ef_curb261

A seguir, inclua o código abaixo para criar cada stored procedure:

1. sp_InserirAluno

CREATE PROCEDURE [dbo].[sp_InserirAluno]
        @PadraoId int = null,
        @AlunoNome varchar
    AS
    BEGIN
        SET NOCOUNT ON;
         INSERT INTO [EscolaDB].[dbo].Aluno([AlunoNome],[PadraoId])
         VALUES(@AlunoNome, @PadraoId)
        SELECT SCOPE_IDENTITY() AS AlunoId
   END

Esta stored procedure usa o comando SELECT SCOPE_IDENTITY() AS AlunoId que permite obter o valor do AlunoId incluído em tempo de execução.

2. sp_AtualizarAluno

-CREATE PROCEDURE [dbo].[sp_AtualizarAluno]
        @AlunoId int,
        @PadraoId int = null,
        @AlunoNome varchar
    AS
    BEGIN
        SET NOCOUNT ON;
        Update [EscolaDB].[dbo].[Aluno] 
        set AlunoNome = @AlunoNome, PadraoId = @PadraoId
        where AlunoId = @AlunoId;
   END

3. sp_DeletarAluno

CREATE PROCEDURE [dbo].[sp_DeletarAluno]
        @AlunoId int
    AS
    BEGIN
        SET NOCOUNT ON;
        DELETE FROM [dbo].[Aluno]
        where AlunoId = @AlunoId
    END

Ao final do processo você deverá ver as stored procedures criadas no banco de dados conforme figura a seguir:

ef_curb262

A seguir, como já criamos o EDM nas aulas anteriores, temos que atualizar o nosso modelo de entidades incluindo as stored procedures que acabamos de criar no EDM.

Abra o EDM na solução EF6_EscolaDB e, em seguida, clique com o botão direito do mouse no interior do descritor e, logo após, em Update Model from database.

No janela do assistente, marque o item Stored Procedures and Functions e clique no botão Finish.

ef_curb252

Se visualizarmos o Model Browser, iremos visualizar a nossa stored procedure em Entity Types -> Complex Types:

ef_curb253

Abra o Model Browser e clique em Stored Procedures / Functions para visualizar as stores procedures importadas:

ef_curb263

Agora clique na entidade Aluno no descritor EDM e, a seguir, clique em Stored Procedure Mapping:

ef_curb264

Na janela Mapping Details você verá as Functions : <Select Insert Function>, <Select Update Function>, e <Select Delete Function>.

Em cada Function selecione a respective stored procedure clicando e escolhendo da lista exibida:

ef_curb266

Ao final do processo, teremos o seguinte mapeamento definido para cada stored procedure:

ef_curb267

A stored procedure sp_InserirAluno retorna o novo Id do aluno gerado na inclusão e, por isso, precisamos mapear o AlunoId da entidade Aluno para o código do aluno – AlunoId (Int32) da tabela Aluno:

ef_curb26b

Para concluir, clique com o botão direito sobre a entidade Aluno e, a seguir, clique em Validate e certifique-se que não tenha nenhum erro.

Pronto! Já podemos usar as nossas stored procedure criadas para realizar o CUD (Create, Update e Delete).

Preparando o ambiente

Vamos usar a solução criada na aula Entity Framework – Consultas Projeção – EF6_EscolaDB -, para testar o cenário da concorrência descrito acima.

Abra a solução EF6_EscolaDB e clique no menu FILE -> Add -> New Project.

Selecione a linguagem Visual C# e o template Console Application e informe o nome EF6_StoredProcedure_CRUD:

ef_curb268

Para referenciar o EF no projeto incluído, no menu TOOLS clique em Nuget Package Manager -> Manage Nuget Packages for solution.

A seguir, clique em Installed packages e depois no botão Manage e marque o projeto que incluímos e, a seguir, no botão OK.

ef_curb269

Depois inclua uma referência ao projeto EF6_EscolaDB e atualize também o arquivo App.Config com a string de conexão para a entidade:

...
<connectionStrings>
<add name="EscolaDBEntities" connectionString="metadata=res://*/EscolaDB.csdl|res://*/EscolaDB.ssdl|res://*/EscolaDB.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\SQLEXPRESS;initial catalog=EscolaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" /></connectionStrings>
...

Testando a Stored Procedure

A seguir, no método Main() do arquivo Program.cs inclua o código abaixo para testar cada uma das stored procedures criadas:

using System;
using EF6_EscolaDB;
namespace EF6_StoredProcedures_CRUD
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new EscolaDBEntities())
            {
                try
                {
                     context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
                    Console.WriteLine("Inserindo um novo Aluno");
                    Aluno novoAluno = new Aluno() { AlunoNome = "Novo Aluno Aula 26", PadraoId = 2 };
                    context.Alunos.Add(novoAluno);
                    //irá executar a stored procedure sp_InserirAluno
                    context.SaveChanges();
                    Console.WriteLine("Novo aluno inserido, tecle algo para alterar o nome");
                    Console.ReadKey();
                    Console.WriteLine("Alterando o nome do Aluno inserido");
                    novoAluno.AlunoNome = "Nome Alterado - Aula 26";
                    //irá executar a stored procedure sp_AlterarAluno
                    context.SaveChanges();
                    Console.WriteLine("Nome Alterado, tecle algo para excluir o aluno");
                    Console.ReadKey();
                    Console.WriteLine("Deleta Aluno - Aula 26");
                    context.Alunos.Remove(novoAluno);
                    //irá executar a stored procedure sp_DeletarAluno
                    context.SaveChanges();
                    Console.WriteLine("Aluno excluido, tecle algo para encerrar");
                    Console.ReadKey();
                }
                catch(Exception ex)
                {
                    Console.WriteLine("Erro : " + ex.Message);
                }
            }
        }
    }
}

Executando o projeto, iremos obter o seguinte resultado:

ef_curb26a

Visualizando o log na janela Debug OutPut veremos a resultado da execução de cada stored procedure conforme abaixo:

Started transaction at 23/10/2015 11:49:14 -02:00
[dbo].[sp_InserirAluno]

-- PadraoId: '2' (Type = Int32)
-- AlunoNome: 'Novo Aluno Aula 26' (Type = AnsiString, Size = 8000)

-- Executing at 23/10/2015 11:49:15 -02:00
-- Completed in 1 ms with result: SqlDataReader

Committed transaction at 23/10/2015 11:49:15 -02:00
Closed connection at 23/10/2015 11:49:15 -02:00
Opened connection at 23/10/2015 11:49:15 -02:00
Started transaction at 23/10/2015 11:49:15 -02:00
[dbo].[sp_AtualizarAluno]
-- AlunoId: '20' (Type = Int32)
-- PadraoId: '2' (Type = Int32)
-- AlunoNome: 'Nome Alterado - Aula 26' (Type = AnsiString, Size = 8000)

-- Executing at 23/10/2015 11:49:15 -02:00
-- Completed in 2 ms with result: -1
Committed transaction at 23/10/2015 11:49:15 -02:00
Closed connection at 23/10/2015 11:49:15 -02:00
Opened connection at 23/10/2015 11:49:17 -02:00
Started transaction at 23/10/2015 11:49:17 -02:00
[dbo].[sp_DeletarAluno]

-- AlunoId: '20' (Type = Int32)

-- Executing at 23/10/2015 11:49:17 -02:00
-- Completed in 26 ms with result: -1
Committed transaction at 23/10/2015 11:49:17 -02:00
Closed connection at 23/10/2015 11:49:17 -02:00

Note que o código do aluno (AlunoId) é obtido a partir da stored procedure sp_IncluirAluno (SELECT SCOPE_IDENTITY() AS AlunoId).

Na próxima aula veremos o suporte a Enum no Entity Framework.