Na primeira parte deste artigo, criamos o banco de dados e geramos o contexto do Entity Framework para o modelo. Agora, vamos começar a definir o componente para o pattern Repository. Segue uma lista dos requisitos para o componente:

Deverá oferecer a possibilidade de trabalhar independente dos tipos envolvidos

Ou seja, poderemos usar o mesmo componente para persistir qualquer objeto, independente do contexto usado. Isso é facilmente conseguido através do uso de Generic Types, sendo possível parametrizar os tipos que serão trabalhados durante as operações de persistência.

Deverá simplificar o desenvolvimento para as rotinas básicas de persistência

O objetivo será tornar o desenvolvimento o mais simples possível, procurando encapsular todo o “trabalho sujo” e criar uma interface limpa e amigável para o programador.

Baseado nas especificações acima, segue a Interface do componente Repository para o Entity Framework:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Linq.Expressions;
   5:  
   6: namespace Net.Bragil.Data.Repository
   7: {
   8:     /// <summary>
   9:     /// Interface para a implementação do padrão Repository usando o Entity Framework.
  10:     /// </summary>
  11:     /// <typeparam name="E">Tipo do objeto persistente</typeparam>
  12:     /// <typeparam name="C">Tipo do contexto do Entity Framework</typeparam>
  13:     public interface IRepository<E, C>
  14:     {
  15:         /// <summary>
  16:         /// Contexto do Entity Framework
  17:         /// </summary>
  18:         C Context { get; set; }
  19:  
  20:         /// <summary>
  21:         /// Inserção
  22:         /// </summary>
  23:         void Insert(E entity);
  24:  
  25:         /// <summary>
  26:         /// Atualização
  27:         /// </summary>
  28:         void Update(E entity);
  29:  
  30:         /// <summary>
  31:         /// Exclusão
  32:         /// </summary>
  33:         void Delete(E entity);
  34:  
  35:         /// <summary>
  36:         /// Retorna o objeto que satisfaça a cláusula passada como argumento (cláusula WHERE)
  37:         /// </summary>
  38:         E SelectOne(Expression<Func<E, bool>> where);
  39:  
  40:         /// <summary>
  41:         /// Retorna todos os objetos de um tipo
  42:         /// </summary>
  43:         List<E> SelectAll();
  44:  
  45:         /// <summary>
  46:         /// Retorna os objetos usando paginação
  47:         /// </summary>
  48:         List<E> SelectAll(int maximumRows, int startRowIndex);
  49:  
  50:         /// <summary>
  51:         /// Retorna todos os objetos que satisfaçam a cláusula passada
  52:         /// </summary>
  53:         /// <param name="where">Cláusula WHERE</param>
  54:         List<E> SelectWhere(Expression<Func<E, bool>> where);
  55:  
  56:         /// <summary>
  57:         /// Retorna os objetos que satisfaçam a cláusula passada, usando paginação
  58:         /// </summary>
  59:         /// <param name="where">Cláusula WHERE</param>
  60:         List<E> SelectWhere(Expression<Func<E, bool>> where, int maximumRows, int startRowIndex);
  61:  
  62:         /// <summary>
  63:         /// Retorna um objeto IQueryable, possibilitando formar queries usando expressões Lambda
  64:         /// </summary>
  65:         IQueryable<E> QueryAll();
  66:  
  67:         /// <summary>
  68:         /// Retorna um IQueryable com os objetos usando paginação
  69:         /// </summary>
  70:         IQueryable<E> QueryAll(int maximumRows, int startRowIndex);
  71:  
  72:         /// <summary>
  73:         /// Retorna a quantidade de objetos persistentes.
  74:         /// </summary>
  75:         int GetCount();
  76:  
  77:         /// <summary>
  78:         /// Retorna a quantidade de objetos persistentes que satisfaçam a cláusula WHERE
  79:         /// </summary>
  80:         int GetCount(Expression<Func<E, bool>> where);
  81:     }
  82: }

Como você pode ver, o componente oferecerá a maioria dos recursos de persistência, de uma forma muito mais amigável do que usando o Entity Framework diretamente.

Foi necessário também a criação de uma classe auxiliar para instanciação do contexto do Entity Framework usando a estratégia “One-Per-Request”, ou seja, é criada apenas uma instância do contexto por requisição. O objeto do contexto é armazenado em HttpContext.Current.Items, de modo que as chamadas subsequentes dentro da mesma requisição retornam o contexto anteriormente instanciado e armazenado na requisição. Segue o código:

   1: using System.Web;
   2: using System.Data.Objects;
   3:  
   4: namespace Net.Bragil.Data.Context
   5: {
   6:     /// <summary>
   7:     /// Classe gerenciadora do contexto do Entity Framework. Utiliza generics para determinar em tempo de execução o 
   8:     /// tipo do contexto e Reflection para instanciar o tipo genérico. Armazena o contexto no HttpContext, de modo que 
   9:     /// não seja necessário instanciar o contexto nas próximas chamadas dentro da requisição web.
  10:     /// </summary>
  11:     public sealed class ContextManager
  12:     {
  13:         /// <summary>
  14:         /// Construtor privado, não será possível instanciar a classe usando new
  15:         /// </summary>
  16:         private ContextManager()
  17:         {
  18:         }
  19:  
  20:         /// <summary>
  21:         /// Obtém o contexto do Entity Framework usando generics.
  22:         /// </summary>
  23:         /// <typeparam name="T">Tipo do contexto do Entity Framework (deve herdar de ObjectContext)</typeparam>
  24:         /// <returns>Contexto do Entity Framework</returns>
  25:         public static T GetContext<T>()
  26:             where T: ObjectContext
  27:         {
  28:             string ocKey = "ocm_" + HttpContext.Current.GetHashCode().ToString("x");
  29:             if (HttpContext.Current != null)
  30:             {
  31:                 if (!HttpContext.Current.Items.Contains(ocKey))
  32:                 {
  33:                     // Instancia o contexto através de Reflection
  34:                     T ctx = typeof(T).GetConstructor(System.Type.EmptyTypes).Invoke(System.Type.EmptyTypes) as T;
  35:                     // Armazena na requisição
  36:                     HttpContext.Current.Items.Add(ocKey, ctx);
  37:                 }
  38:                 return HttpContext.Current.Items[ocKey] as T;
  39:             }
  40:             else
  41:                 // Caso a aplicação não seja web, instancia e retorna o contexto.
  42:                 return typeof(T).GetConstructor(System.Type.EmptyTypes).Invoke(System.Type.EmptyTypes) as T;
  43:             
  44:         }
  45:  
  46:     }
  47: }

Já estamos quase lá! No próximo artigo vamos desenvolver a implementação da classe EFRepository.


Páginas

Calendário

«  September 2010  »
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
View posts in large calendar