À medida que me aprofundo no DbContext, no DbSet e nas interfaces associadas, fico imaginando por que você precisaria implementar um repositório "genérico" separado em torno dessas implementações?
Parece que o DbContext e o IDbSet fazem tudo o que você precisa e inclui a "Unidade de trabalho" dentro do DbContext.
Estou faltando alguma coisa aqui ou parece que as pessoas gostam de adicionar outra camada de dependência sem motivo.
repository-pattern
entity-framework-4.1
unit-of-work
Code Jammr
fonte
fonte
Respostas:
Você está realmente certo.
DbContext
é uma implementação do padrão de unidade de trabalho eIDbSet
é uma implementação do padrão de repositório.Atualmente, os repositórios são muito populares e usados em excesso. Todos os usam apenas porque existem dezenas de artigos sobre a criação de repositório para a estrutura da entidade, mas ninguém descreve os desafios relacionados a essa decisão.
Os principais motivos para usar o repositório são geralmente:
A primeira razão é algum tipo de pureza arquitetônica e uma ótima idéia de que, se você tornar suas camadas superiores independentes do EF, poderá posteriormente mudar para outra estrutura de persistência. Quantas vezes você viu isso no mundo real? Esse motivo torna o trabalho com o EF muito mais difícil, porque seu repositório deve expor muitos recursos adicionais, abrangendo o que o EF permite por padrão.
Ao mesmo tempo, o acondicionamento do código EF pode manter seu código melhor organizado e seguindo a regra de separação de preocupações. Para mim, essa pode ser a única vantagem real do repositório e da unidade de trabalho, mas você precisa entender que seguir esta regra com a EF talvez torne seu código mais fácil de manter e de melhor legibilidade, mas no esforço inicial para criar seu aplicativo será muito maior e para aplicativos menores, isso pode ser uma complexidade desnecessária.
O segundo motivo está parcialmente correto. A grande desvantagem do EF é a arquitetura rígida, que dificilmente pode ser ridicularizada; portanto, se você deseja testar a camada superior da unidade, é necessário agrupar o EF de alguma forma para permitir que sua implementação seja ridicularizada. Mas isso tem muitas outras consequências que descrevi aqui .
Eu sigo o blog de Ayende . Se você já usou o NHibernate, provavelmente conhece os artigos dele. Esse cara recentemente escreveu vários artigos contra o uso de repositório com o NHibernate, mas o NHibernate é muito melhor ridicularizável.
fonte
IDbSet
também pode definir a interface personalizada no seu contexto derivado, mas isso é tudo. Depois que seu código usar o ChangeTracker, Entries ou o que mais for necessário, será necessário um grande esforço para agrupar todos eles.IQueryable
ou aceitaExpression<>
como parâmetro que é internamente colocado na consulta Linq-para-entidades, você está definindo a lógica fora do componente simulado com efeitos colaterais que não podem ser testados com testes de unidade.Estou enfrentando os mesmos problemas, e a simulabilidade para testes de unidade das camadas EF é importante. Mas eu deparei com este ótimo artigo que explica como configurar o EF 4.1 DbContext para ser ridicularizável, certificando-se de que o DbContext derivado implementou uma interface genérica e expõe o IDbSet em vez do DbSet. Como estou usando uma abordagem do Database First, porque nosso banco de dados já existe, simplesmente modifiquei os modelos T4 usados para gerar meu DbContext derivado para gerá-lo para retornar interfaces IDbSet e derivar da minha interface genérica. Dessa forma, tudo pode ser facilmente zombado e você não precisa implementar sua própria Unidade de Trabalho ou padrão de repositório. Basta escrever seu código de serviço para consumir sua interface genérica e, quando for testá-lo,
http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/
fonte
Uma razão para criar o repositório é para que você possa ocultar a implementação do DBSet e DbContext se decidir mudar do EntityFramework para outra coisa ou vice-versa.
Por exemplo, eu estava usando o NHibernate e agrupei todas as chamadas para essa estrutura nas minhas classes de repositório. Eles retornam IEnumerable para que seus get sejam "genéricos" e meus repositórios têm as operações CRUD padrão (atualização, exclusão, etc.). Há muito que mudei para o Entity Framework. Ao fazer isso, não precisei alterar nada nas minhas classes ViewModel ou mais além, porque elas apontavam para o meu repositório - eu só precisava alterar o interior do meu repositório. Isso tornou a vida muito mais fácil ao migrar.
(Eu usei o NHibernate porque estamos nos conectando ao ISeries e, na época, não havia implementações afetivas de custo usando EF com o ISeries. O único disponível era pagar US $ 12.000 à IBM pelo DB2Connect)
fonte