Desenvolvimento - ASP. NET

Entity Framework: Utilizando procedures para o CRUD

Veja neste artigo como mapear stored procedures para realizar as operações de insert, update e delete referentes a uma entidade, substituindo o comportamento padrão e executando suas próprias instruções customizadas.

por Joel Rodrigues



Quando utilizamos o Entity Framework para realizar as principais operações relacionadas a bancos de dados de uma aplicação (CRUD), grande parte do trabalho de escrever instruções SQL é poupada, uma vez que o EF fica responsável por essa parte do processo e executa tudo internamente, sem que o desenvolvedor precise escrever as instruções de banco de dados diretamente.

Considerando o caso mais simples, e também o mais comum, que é a realização das operações de CRUD (Create, Retrieve, Update and Delete, ou seja, Criação, Leitura, Atualização e Exclusão de registros), basta que efetuemos o mapeamento da tabela e a partir daí podemos fazer uso da arquitetura completamente orientada a objetos do EF. As operações SQL não precisam ser escritas diretamente na aplicação, bastando utilizar métodos como Add e Remove nas próprias classes geradas no mapeamento.

As instruções SQL são geradas pelo próprio frameworks e executadas sem que o desenvolvedor precise se preocupar em escrever inserts, updates, deletes ou selects.

Porém, existem casos em que empresas (ou desenvolvedores individualmente) optam por utilizar stored procedures para realizar essas operações. Nesses procedures geralmente são inseridas regras de negócio, validações e processos de automatização.

Esse tipo de prática é mais comum em projetos que utilizam datasets tipados, que em sua configuração já preveem essa situação e permitem que o desenvolvedor selecione quais procedures existentes no banco serão responsáveis por tais operações.

Como o Entity Framework é o mecanismo de acesso a dados mais moderno e atualizado atualmente do .NET Framework, é natural que projetos sejam migrados ou que novos projetos façam uso dessa tecnologia. Porém, existem casos em que é necessário manter esse formato de utilização de procedures para realizar o CRUD e, como era de se esperar, o EF possui suporte para esse tipo de situação.

Criando o banco de exemplo

Para tornar a explicação mais clara, trabalharemos aqui com um exemplo prático, onde criaremos uma tabela e três stored procedures para mapear as operações de insert, update e delete. A Listagem 1 contém o código completo do banco utilizado no exemplo.

Listagem1: Estrutura do banco utilizado

create table Produtos
(
	Codigo		int primary key,
	Descricao	varchar(100) unique,
	Preco		decimal(10,2)
)
go

create procedure usp_Produtos_Insert
	@Codigo		int,
	@Descricao	varchar(100),
	@Preco		decimal(10,2)
as
begin
	if not exists(select Codigo from Produtos where Codigo = @Codigo)
	begin
		insert into Produtos(Codigo, Descricao, Preco) values (@Codigo, @Descricao + ' - NOVO', @Preco)
	end
end
go

create procedure usp_Produtos_Update
	@Codigo		int,
	@Descricao	varchar(100),
	@Preco		decimal(10,2)
as
begin
	update Produtos set Descricao = @Descricao + ' - ATUALIZADO', Preco=@Preco
	where Codigo = @Codigo
end
go

create procedure usp_Produtos_Delete
	@Codigo		int
as
begin
	delete from Produtos
	where Codigo = @Codigo
end
go

Mapeando as tabelas e procedures

Com o banco pronto, criaremos uma aplicação ASP.NET MVCe adicionaremos um ADO.NET Entity DataModel na pasta Models, um procedimento comum nesse tipo de aplicação.

Ao criar o Data Model, além de selecionar a tabela Produtos na seção Tables, devemos selecionar também os três procedures na seção Stored Procedures and Functions, como mostra a Figura 1.

Importando os procedures na criação do Data Model

Figura 1: Importando os procedures na criação do Data Model

Nota: essa importação também pode ser feita posteriormente à criação do Data Model, bastando clicar com a direita na parte branca do modelo e no menu Update Model from Database.

Feito isso, o próximo passo é criar as funções que serão responsáveis por executar esses procedures, ou seja, realizar o mapeamento dos procedures em funções, assim como as tabelas são mapeadas como classes e coleções dessas.

Para isso, clica-se com a direita na parte branca do modelo, e então no menu Add New > Function Import, conforme a Figura 2.

Mapeando os procedures

Figura 2: Mapeando os procedures

Na janela que se abrirá (Figura 3), selecione um dos procedures e dê um nome à função equivalente. Repita o procedimento para os três procedures criados.

Criando função para mapear procedure

Figura 3: Criando função para mapear procedure

Agora que já temos as funções criadas, podemos ligá-las à tabela mapeada de Produtos. Clicando com a direita sobre a entidade Produtos no Data Model, devemos usar a opção Stored Procedure Mapping, como vemos na Figura 4.

Mapear procedures para a entidade

Figura 4: Mapear procedures para a entidade

Na parte inferior do Visual Studio, surgirá uma aba chamada Mapping Details, que pode ser vista na Figura 5. Nela encontramos os campos onde devemos selecionar as funções que serão responsáveis pelas operações de insert, update e delete. Clicando em cada uma delas, devemos escolher uma das funções que criamos anteriormente.

Selecionar as funções de insert, update e delete

Figura 5: Selecionar as funções de insert, update e delete

Quando selecionarmos cada função, alguns detalhes serão exibidos logo abaixo (Figura 6). Analisando esses detalhes, observamos o relacionamento entre os parâmetros do procedure e a propriedade equivalente na entidade. Em geral mantemos o padrão, mas se for necessário, pode-se escolher qualquer campo com tipo adequado para preencher os parâmetros.

Relacionamento entre as propriedades da entidade e os parâmetros do procedure

Figura 6: Relacionamento entre as propriedades da entidade e os parâmetros do procedure

Nota: a operação de select não é mapeada da mesma forma, uma vez que esse as consultas geralmente são efetuadas com LINQ.

Para testar, podemos criar um controller para o model Produtos e acessar no browser. Ao inserirmos um novo produto e voltarmos para a página de listagem, veremos que a descrição que inserimos foi modificada, recebendo “ – NOVO” no final (Figura 7). Isso foi configurado em nosso stored procedure de insert, apenas para exemplificar o funcionamento deste mapeamento.

Registro inserido através do stored procedure

Figura 7: Registro inserido através do stored procedure

Figura 7: Registro inserido através do stored procedure

Se alteramos o registro, veremos que a descrição receberá “ – ATUALIZADO” no final, o que foi definido no store procedure de update, no início deste artigo.

Na prática, como já foi dito, nos procedures pode haver implementação de regras de negócio, validações e automatizações, dependendo de cada necessidade.

Finalizamos aqui este artigo. Até a próxima.

Joel Rodrigues

Joel Rodrigues - Técnico em Informática - IFRN Cursando Bacharelado em Ciências e Tecnologia - UFRN Programador .NET/C# e Delphi há quase 3 anos, já tendo trabalhado com Webservices, WPF, Windows Phone 7 e ASP.NET, possui ainda conhecimentos em HTML, CSS e Javascript (JQuery).