Eu apenas tive que mudar um ORM e foi uma tarefa relativamente assustadora, porque a lógica da consulta estava vazando por toda parte. Se eu tivesse que desenvolver um novo aplicativo, minha preferência pessoal seria encapsular toda a lógica de consulta (usando um ORM) para protegê-lo de alterações no futuro. Padrão de repositório é bastante problemático para codificar e manter, então eu queria saber se existem outros padrões para resolver o problema?
Posso prever postagens sobre não adicionar complexidade extra antes que seja realmente necessário, ser ágil etc., mas estou interessado apenas nos padrões existentes que resolvem um problema semelhante de uma maneira mais simples.
Meu primeiro pensamento foi ter um repositório de tipos genéricos, ao qual adiciono métodos conforme necessário a classes de repositórios de tipos específicos por meio de métodos de extensão, mas os métodos estáticos de teste de unidade são terrivelmente dolorosos. IE:
public static class PersonExtensions
{
public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep)
{
// logic
}
}
fonte
Respostas:
Primeiro de tudo: um repositório genérico deve ser considerado uma classe base e não implementações completas. Isso deve ajudá-lo a implementar os métodos CRUD comuns. Mas você ainda precisa implementar os métodos de consulta:
Segundo:
Não volte
IQueryable
. É uma abstração com vazamento. Tente implementar você mesmo essa interface ou use-a sem conhecimento sobre o provedor de banco de dados subjacente. Por exemplo, todo provedor de banco de dados tem sua própria API para carregar entidades com entusiasmo. É por isso que é uma abstração com vazamento.Alternativo
Como alternativa, você pode usar consultas (por exemplo, conforme definido pelo padrão de separação Comando / Consulta). O CQS é descrito na wikipedia.
Você basicamente cria classes de consulta que você chama:
o melhor das consultas é que você pode usar métodos diferentes de acesso a dados para consultas diferentes sem sobrecarregar o código. você pode, por exemplo, usar um serviço da web em um, inibir em outro e ADO.NET em um terceiro.
Se você estiver interessado em uma implementação .NET, leia meu artigo: http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/
fonte
YourProject.YourDomainModelName.Queries
, será fácil navegar.Primeiro, acho que digo que o ORM já é suficientemente grande para abstração no seu banco de dados. Alguns ORMs fornecem ligação a todos os bancos de dados relacionais comuns (o NHibernate possui ligações ao MSSQL, Oracle, MySQL, Postgress, etc.). Portanto, criar uma nova abstração em cima dela não me parece rentável. Além disso, argumentar que você precisa "abstrair" esse ORM não faz sentido.
Se você ainda deseja construir essa abstração, eu iria contra o padrão do Repositório. Foi ótimo na era do SQL puro, mas é bastante problemático diante do ORM moderno. Principalmente porque você acaba reimplementando a maioria dos recursos do ORM, como operações e consultas CRUD.
Se eu fosse construir tais abstrações, usaria essas regras / padrões
Na implementação concreta, eu usaria operações CRUD do ORM diretamente, sem nenhuma quebra. Eu também faria consultas simples diretamente no código. Mas consultas complexas seriam encapsuladas em seus próprios objetos. Para "ocultar" o ORM, tentaria injetar o contexto de dados de forma transparente em objetos de serviço / interface do usuário e faria o mesmo para consultar objetos.
A última coisa que gostaria de dizer é que muitas pessoas usam o ORM sem saber como usá-lo e como obter o melhor "lucro" dele. As pessoas que recomendam repositórios geralmente são desse tipo.
Como leitura recomendada, diria o blog de Ayende , especialmente este artigo .
fonte
O problema com a implementação com vazamento é que você precisa de muitas condições de filtro diferentes.
Você pode restringir essa API se implementar um método de repositório FindByExample e usá-lo desta maneira
fonte
Considere fazer suas extensões operar no IQueryable em vez do IRepository.
Para teste de unidade:
Nenhuma zombaria de financiamento é necessária para o teste. Você também pode combinar esses métodos de extensão para criar consultas mais complexas, conforme necessário.
fonte
IQueryable
é uma mãe ruim, ou melhor, uma interface GOD. Implementá-lo é muito necessário e existem muito poucos (se houver) fornecedores completos de LINQ to Sql. b) Os métodos de extensão tornam impossível a extensão (um dos princípios fundamentais de POO).Eu escrevi um padrão de objeto de consulta bastante elegante para o NHibernate aqui: https://github.com/shaynevanasperen/NHibernate.Sessions.Operations
Funciona usando uma interface como esta:
Dada uma classe de entidade POCO como esta:
Você pode criar objetos de consulta como este:
E depois use-os assim:
fonte