repositorio - repository crud c#



Repositório genérico ou repositório específico para cada entidade? (1)

Para começar, se você estiver usando ORM completo, como Entity Framework ou NHibernate, deverá evitar a implementação de camada adicional de Repositório e Unidade de Trabalho. Isto é porque; o próprio ORM expõe o Repositório Genérico e a Unidade de Trabalho.
No caso de EF, seu DbContext é Unit Of Work e DbSet é Generic Repository. No caso do NHibernate, é a própria ISession .
Construir um novo wrapper do Repositório Genérico sobre o mesmo existente é repetir o trabalho. Por que reinventar a roda?

Mas , alguns argumentam que o uso do ORM diretamente no código de chamada tem os seguintes problemas:

  1. Isso torna o código um pouco mais complicado.
  2. O código de acesso a dados é mesclado na lógica de negócios.
  3. Como muitos objetos ORM são usados ​​in-line no código de chamada, é muito difícil testar o código.
  4. Como o ORM expõe apenas o Repositório Genérico, ele causa muitos problemas mencionados abaixo.

Além de tudo, uma outra questão geralmente discutida é "E se decidirmos mudar o ORM no futuro". Este não deve ser o ponto chave ao tomar a decisão porque:

  • Você raramente muda ORM, principalmente NUNCA - YAGNI.
  • Se você alterar o ORM, terá que fazer grandes alterações de qualquer maneira. Você pode minimizar os esforços encapsulando o código de acesso completo aos dados (NÃO apenas ORM) dentro de algo . Vamos discutir algo abaixo.

Considerando quatro questões mencionadas acima, pode ser necessário criar Repositórios, mesmo que você esteja usando ORM completo - Isso é uma decisão por caso .

Mesmo nesse caso, o Repositório Genérico deve ser evitado. É considerado um anti-padrão.

Por que repositório genérico é anti-padrão?

  1. Um repositório é uma parte do domínio que está sendo modelado e esse domínio não é genérico.
    • Nem toda entidade pode ser excluída.
    • Nem toda entidade pode ser adicionada
    • Nem toda entidade possui um repositório.
    • As consultas variam muito; a API do repositório se torna tão exclusiva quanto a própria entidade.
    • Para GetById() , os tipos de identificador podem ser diferentes.
    • A atualização de campos específicos (DML) não é possível.
  2. O mecanismo genérico de consulta é de responsabilidade de um ORM.
    • A maioria dos ORMs expõe uma implementação que se parece muito com o Repositório Genérico.
    • Os repositórios devem implementar as consultas específicas para entidades usando o mecanismo de consulta genérica exposto pelo ORM.
  3. Trabalhar com chaves compostas não é possível.
  4. Ele vaza a lógica DAL nos Serviços de qualquer maneira.
    • Os critérios de predicados, se você aceitar como parâmetro, precisam ser fornecidos a partir da camada de serviço. Se essa for uma classe específica de ORM, ela vazará ORM para os Serviços.

Eu sugiro que você leia estes ( 1 , 2 , 3 , 4 , 5 ) artigos explicando porque o repositório genérico é um anti-padrão. Essa other resposta discute sobre o Padrão de Repositório em geral.

Então, vou sugerir:

  • NÃO use repositório, use diretamente o ORM em seu código de chamada.
  • Se você tiver que usar o repositório, não tente implementar tudo com o Repositório Genérico.
    Em vez disso, opcionalmente, crie um Repositório Genérico muito simples e pequeno como classe base abstrata. OU você pode usar o Repositório Genérico exposto pelo seu ORM como repositório base, se o ORM permitir.
    Implemente Repositórios Concretos conforme sua necessidade e obtenha todos eles do Repositório Genérico. Expor repositórios concretos ao código de chamada.
    Dessa forma, você obtém todo o bem do repositório genérico ainda ignorando suas desvantagens.
    Mesmo sendo muito raro, isso também ajuda a mudar o ORM no futuro, já que o código ORM é resumido de forma limpa em DAL / Repositórios. Por favor, entenda que trocar ORM não é um objetivo primário da Camada de Acesso a Dados ou do Repositório.

Em qualquer caso, não exponha o Repositório Genérico ao código de chamada.

Além disso, não retorne o IQueryable de repositórios concretos. Isso viola a finalidade básica da existência de Repositórios - Para abstrair o acesso a dados. Com a exposição do IQueryable fora do repositório, muitas decisões de acesso a dados perdem para o código de chamada e o Repositório perde o controle sobre ele.

Preciso criar um repositório para cada entidade ou implementar um repositório genérico para o contexto

Como sugerido acima, criar um repositório para cada entidade é uma abordagem melhor. Observe que, idealmente, o Repositório deve retornar o Modelo de Domínio em vez da Entidade. Mas este é um tópico diferente para discussão.

um repositório genérico funciona para o EF Database First?

Como sugerido acima, a própria EF expõe o Repositório Genérico. Construir mais uma camada é inútil. Sua imagem está dizendo a mesma coisa.

fundo

Na empresa em que trabalho, recebi uma ordem para atualizar um aplicativo MVC antigo e implementar um padrão de repositório para um banco de dados SQL. Eu criei o contexto do banco de dados usando Entity Framework Database-First e tenho 23 entidades.

A primeira pergunta

Preciso criar um repositório para cada entidade ou implementar um repositório genérico para o contexto? Estou perguntando isso porque eu encontrei seguindo enquanto pesquisava na internet:

Um repositório por domínio

Você deve pensar em um repositório como uma coleção de objetos de domínio na memória. Se você está construindo uma aplicação chamada Vega, você não deve ter um repositório como o seguinte:

public class VegaRepository {}

Fonte: Programação com Mosh: 4 erros comuns com o padrão de repositório

A segunda pergunta

Um repositório genérico funciona para o banco de dados do Entity Framework First? Isso é porque eu encontrei seguindo enquanto pesquisava internet:

Estrutura de entidade

Observe que o padrão de repositório é útil apenas se você tiver POCOs que são mapeados usando o código primeiro. Caso contrário, você apenas quebrará a abstração com as entidades (o padrão do repositório não é muito útil). Você pode seguir este artigo se quiser obter uma base gerada para você.

Fonte: CodeProject: Padrão de Repositório, feito direito





generic-repository