1: using System;
2: using System.Collections.Generic;
3: using System.Data;
4: using System.Data.Metadata.Edm;
5: using System.Data.Objects;
6: using System.Data.Objects.DataClasses;
7: using System.Linq;
8: using System.Linq.Expressions;
9: using Net.Bragil.Data.Context;
10:
11: namespace Net.Bragil.Data.Repository
12: {
13: /// <summary>
14: /// Repositório genérico para o Entity Framework com as operações mais comuns de persistência, como inserção, atualização,
15: /// exclusão e seleção.
16: /// </summary>
17: /// <typeparam name="E">Tipo do objeto a ser persistido</typeparam>
18: /// <typeparam name="C">Tipo do contexto</typeparam>
19: public class EFRepository<E, C> : IRepository<E, C>, IDisposable
20: where E : EntityObject
21: where C : ObjectContext
22: {
23: /// <summary>
24: /// Contexto do Entity Framework
25: /// </summary>
26: private C context;
27:
28: /// <summary>
29: /// Contexto do Entity Framework
30: /// </summary>
31: public C Context
32: {
33: get { return context; }
34: set { context = value; }
35: }
36:
37: /// <summary>
38: /// Retorna o nome do EntitySet do objeto persistente
39: /// </summary>
40: private string entitySetName;
41:
42: /// <summary>
43: /// Retorna o nome do EntitySet do objeto persistente
44: /// </summary>
45: protected string EntitySetName
46: {
47: get
48: {
49: if (String.IsNullOrEmpty(entitySetName))
50: {
51: entitySetName = GetEntitySetName(typeof(E).Name);
52: }
53: return entitySetName;
54: }
55: }
56:
57: /// <summary>
58: /// Construtor padrão, sem argumentos. Obtém o contexto do Entity Framework usando o ContextManager.
59: /// </summary>
60: public EFRepository()
61: {
62: // Obtém o contexto
63: this.context = ContextManager.GetContext<C>();
64: }
65:
66: /// <summary>
67: /// Insere um novo objeto persistente
68: /// </summary>
69: /// <param name="entity">Objeto a ser inserido</param>
70: public void Insert(E entity)
71: {
72: context.AddObject(EntitySetName, entity);
73: }
74:
75: /// <summary>
76: /// Atualiza um objeto existente.
77: /// </summary>
78: /// <param name="entity">Objeto persistente</param>
79: public virtual void Update(E entity)
80: {
81: EntityKey key;
82: object originalItem;
83: if (entity.EntityKey == null)
84: // Obtém o entity key do objeto que será atualizado
85: key = Context.CreateEntityKey(EntitySetName, entity);
86: else
87: key = entity.EntityKey;
88: try
89: {
90: // Obtém o objeto original
91: if (Context.TryGetObjectByKey(key, out originalItem))
92: {
93: if (originalItem is EntityObject &&
94: ((EntityObject)originalItem).EntityState != EntityState.Added)
95: {
96: // Autaliza o objeto
97: context.ApplyPropertyChanges(key.EntitySetName, entity);
98: }
99: }
100: }
101: catch (Exception ex)
102: {
103: throw ex;
104: }
105:
106: }
107:
108: /// <summary>
109: /// Exclui um objeto persistente
110: /// </summary>
111: /// <param name="entity">Objeto persistente que será excluído</param>
112: public void Delete(E entity)
113: {
114: context.DeleteObject(entity);
115: }
116:
117: /// <summary>
118: /// Retorna um objeto que satisfaça a cláusula passada como parâmetro.
119: /// </summary>
120: /// <param name="expression">Expressão Lambda da cláusula WHERE</param>
121: public E SelectOne(Expression<Func<E, bool>> where)
122: {
123: return context.CreateQuery<E>(EntitySetName).Where(where).FirstOrDefault();
124: }
125:
126: /// <summary>
127: /// Salva as alterações no banco de dados.
128: /// </summary>
129: public void SaveChanges()
130: {
131: context.SaveChanges();
132: }
133:
134: /// <summary>
135: /// Retorna todos os objetos persistentes.
136: /// </summary>
137: /// <returns>Coleção com todos os objetos</returns>
138: public List<E> SelectAll()
139: {
140: return context.CreateQuery<E>(EntitySetName).ToList();
141: }
142:
143: /// <summary>
144: /// Retorna um IQueryable com todos os objetos
145: /// </summary>
146: /// <returns>IQueryable com todos os objetos</returns>
147: public IQueryable<E> QueryAll()
148: {
149: return context.CreateQuery<E>(EntitySetName).AsQueryable<E>();
150: }
151:
152: /// <summary>
153: /// Retorna todos os objetos usando paginação.
154: /// </summary>
155: /// <param name="maximumRows">Quantidade de objetos por página</param>
156: /// <param name="startRowIndex">Linha a partir do qual os objetos serão retornados</param>
157: /// <returns>Coleção com todos os objetos</returns>
158: public List<E> SelectAll(int maximumRows, int startRowIndex)
159: {
160: return context.CreateQuery<E>(EntitySetName).Skip<E>(startRowIndex).Take(maximumRows).ToList();
161: }
162:
163: /// <summary>
164: /// Retorna um IQueryable com todos os objetos usando paginação
165: /// </summary>
166: /// <param name="maximumRows">Quantidade de objetos por página</param>
167: /// <param name="startRowIndex">Linha a partir do qual os objetos serão retornados</param>
168: /// <returns>IQueryable com todos os objetos</returns>
169: public IQueryable<E> QueryAll(int maximumRows, int startRowIndex)
170: {
171: return context.CreateQuery<E>(EntitySetName).Skip<E>(startRowIndex).Take(maximumRows);
172: }
173:
174: /// <summary>
175: /// Retorna todos os objetos que satisfaçam a cláusula passada
176: /// </summary>
177: /// <param name="where">Expressão Lambda da cláusula WHERE</param>
178: public List<E> SelectWhere(Expression<Func<E, bool>> where)
179: {
180: return context.CreateQuery<E>(EntitySetName).Where(where).ToList();
181: }
182:
183: /// <summary>
184: /// Retorna todos os objetos que satisfaçam a cláusula passada, usando paginação
185: /// </summary>
186: /// <param name="where">Expressão Lambda da cláusula WHERE</param>
187: /// <param name="maximumRows">Quantidade de objetos por página</param>
188: /// <param name="startRowIndex">Linha a partir do qual os objetos serão retornados</param>
189: public List<E> SelectWhere(Expression<Func<E, bool>> where, int maximumRows, int startRowIndex)
190: {
191: return context.CreateQuery<E>(EntitySetName).Where(where)
192: .Skip<E>(startRowIndex).Take(maximumRows).ToList();
193: }
194:
195: /// <summary>
196: /// Retorna o número de objetos
197: /// </summary>
198: /// <remarks>Para ser usado na configuração da paginação</remarks>
199: public int GetCount()
200: {
201: return context.CreateQuery<E>(EntitySetName).Count();
202: }
203:
204: /// <summary>
205: /// Retorna o número de objetos que satisfaçam a cláusula passada
206: /// </summary>
207: /// <remarks>Para ser usado na configuração da paginação</remarks>
208: public int GetCount(Expression<Func<E, bool>> where)
209: {
210: return context.CreateQuery<E>(EntitySetName).Where(where).Count();
211: }
212:
213: /// <summary>
214: /// Libera os recursos do Entity Framework.
215: /// </summary>
216: public void Dispose()
217: {
218: if (context != null)
219: context.Dispose();
220: }
221:
222: /// <summary>
223: /// Retorna o nome do EntitySet, possibilitando a criação de métodos genéricos.
224: /// </summary>
225: /// <param name="entityTypeName">String com o nome do tipo</param>
226: /// <returns>String contendo o EntitySet</returns>
227: private string GetEntitySetName(string entityTypeName)
228: {
229: var container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
230: string entitySetName = (from meta in container.BaseEntitySets
231: where meta.ElementType.Name == entityTypeName
232: select meta.Name).FirstOrDefault();
233: return entitySetName;
234: }
235:
236: }
237:
238:
239: }