/// <summary> /// Constrói um item do cache de banco de dados. /// </summary> /// <param name="entidade">Entidade do banco de dados.</param> /// <param name="validade">Validade do item no cache.</param> public CacheDbItem(DbManipulação entidade, DateTime validade, CacheDbChave chave) { this.entidade = entidade; this.validade = validade; this.chave = chave; this.criação = DateTime.Now; this.usos = 0; if (entidade == null) this.copiar = false; else { this.copiar = (entidade.GetType().GetCustomAttributes(typeof(NãoCopiarCache), true).Length == 0); if (copiar) this.entidade.Alterado += new DbManipulação.DbManipulaçãoHandler(AoAlterarEntidade); } }
/// <summary> /// Campos de relacionamento invertido. /// </summary> public DbManipulação[] ObterRelacionamentosInvertidos(DbManipulaçãoAutomática entidade) { DbManipulação[] relacionamentos; relacionamentos = new DbManipulação[vetorRelacionamentoInvertido.Length]; for (int i = 0; i < vetorRelacionamentoInvertido.Length; i++) relacionamentos[i] = (DbManipulação)vetorRelacionamentoInvertido[i].GetValue(entidade); return relacionamentos; }
/// <summary> /// Adiciona uma entidade no cache. /// </summary> /// <param name="tipo">Tipo da entidade.</param> /// <param name="parâmetros">Parâmetros usados para recuperar a entidade.</param> /// <param name="entidade">Entidade.</param> public void Adicionar(Type tipo, object[] parâmetros, DbManipulação entidade) { CacheDbItem item; item = new CacheDbItem(entidade, ExtrairValidade(tipo), new CacheDbChave(tipo, parâmetros)); while (listaCache.Count >= tamanho) Remover(listaCache[0]); hashCache.Add(item.Chave, item); listaCache.Add(item); listaCache.Sort(); #if DEBUG //Console.WriteLine("Adicionado {0} ({1}) em cache. {2} itens em cache.", tipo.ToString(), entidade, listaCache.Count); #endif }
/// <summary> /// Recuperar conforme compatibilidade. /// </summary> /// <returns> verdadeiro se conseguiu. </returns> private static bool RecuperarConvertendo(Type tipo, object [] parâmetros, MethodInfo [] métodos, out DbManipulação entidade) { // Tentar compatibilidade foreach (MethodInfo método in métodos) { ParameterInfo [] métParâmetros; bool válido; métParâmetros = método.GetParameters(); válido = métParâmetros.Length == parâmetros.Length; if (!válido) continue; if (válido) { object[] pConvertidos = new object[parâmetros.Length]; for (int i = 0; i < parâmetros.Length; i++) pConvertidos[i] = Convert.ChangeType(parâmetros[i], métParâmetros[i].ParameterType); entidade = (DbManipulação) método.Invoke(null, pConvertidos); return true; } } entidade = null; return false; }
/// <summary> /// Recuperar conforme compatibilidade. /// </summary> /// <returns> verdadeiro se conseguiu recuperar </returns> private static bool RecuperarCompatibilidade(Type tipo, object [] parâmetros, MethodInfo [] métodos, out DbManipulação entidade) { // Tentar compatibilidade foreach (MethodInfo método in métodos) { ParameterInfo [] métParâmetros; bool válido; métParâmetros = método.GetParameters(); válido = métParâmetros.Length == parâmetros.Length; if (!válido) continue; foreach (ParameterInfo parâmetro in métParâmetros) if (parâmetros[parâmetro.Position] != null) válido &= parâmetro.ParameterType.IsAssignableFrom(parâmetros[parâmetro.Position].GetType()); else válido &= !parâmetro.ParameterType.IsValueType || parâmetro.ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>); if (válido) { entidade = (DbManipulação) método.Invoke(null, parâmetros); return true; } } entidade = null; return false; }
/// <summary> /// Remove item do cache. /// </summary> /// <param name="entidade">Item a ser removido.</param> public void Remover(DbManipulação entidade) { CacheDbItem[] listaAntiga = new CacheDbItem[listaCache.Count]; listaCache.CopyTo(listaAntiga); if (entidade != null) { Type tipo = entidade.GetType(); foreach (CacheDbItem item in listaAntiga) /* O tipo não pode ser comparado. * Imagine que existe um item "Representante" em cache * e deseja-se remover a mesma pessoa porém "PessoaFísica" * Isso acontece na prática! */ ///if (item.Entidade != null && item.Entidade.GetType() == tipo && entidade.Referente(item.Entidade)) if (item.Entidade != null && entidade.Referente(item.Entidade)) { Remover(item); //break; /* Deve-se remover todas as instancias. * Existe caso em que há mais de uma entidade repetida na cache. * Como reproduzir ? Procure pessoa pelo codigo no atendimento faça alguma alteração e procure novamente. */ } } }
/// <summary> /// Ocorre ao alterar a entidade. Uma mudança na entidade /// deve invalidar a entidade na cache. /// </summary> /// <param name="entidade">Entidade alterada.</param> /// <remarks>Só disparado se copiar == true.</remarks> internal void AoAlterarEntidade(DbManipulação entidade) { #if DEBUG Console.WriteLine("Item na cache alterado. Vencendo validade de " + entidade.ToString()); #endif validade = DateTime.MinValue; }
/// <summary> /// Ação ocorrida. /// </summary> /// <param name="entidade">Entidade que sofreu a ação.</param> /// <param name="ação">Ação sofrida.</param> public DbAçãoDados(DbManipulação entidade, DbAção ação) { this.entidade = entidade; this.ação = ação; }