Acredito que, se você tiver seus repositórios, use um ORM que já é suficiente abstraído do banco de dados.
No entanto, onde estou trabalhando agora, alguém acredita que devemos ter uma camada que abstraia o ORM, caso desejemos alterá-lo mais tarde.
É realmente necessário ou é simplesmente muito caro criar uma camada que funcione em muitos ORM?
Editar
Só para dar mais detalhes:
- Temos a classe POCO e a Entity Class que são mapeadas com o AutoMapper. A classe de entidade é usada pela camada Repository. A camada de repositório usa a camada adicional de abstração para se comunicar com o Entity Framework.
- A camada de negócios não tem acesso direto ao Entity Framework. Mesmo sem a camada adicional de abstração no ORM, esta precisa usar a camada de serviço que utiliza a camada de repositório. Nos dois casos, a camada de negócios é totalmente separada do ORM.
- O argumento principal é poder alterar o ORM no futuro. Como ele está realmente localizado dentro da camada Repository, para mim, já está bem separado e não vejo por que uma camada adicional de abstração é necessária para ter um código de "qualidade".
Respostas:
Dessa maneira está a loucura. É altamente improvável que você precise alterar os ORMs. E se você decidir alterar o ORM, o custo de reescrever os mapeamentos será uma pequena fração do custo para desenvolver e manter seu próprio meta-ORM. Eu esperava que você pudesse escrever alguns scripts para fazer 95% do trabalho necessário para alternar ORMs.
As estruturas internas são quase sempre um desastre. Construir um em antecipação às necessidades futuras é quase um desastre garantido. Estruturas bem-sucedidas são extraídas de projetos bem-sucedidos, não construídas com antecedência para atender às necessidades imaginárias.
fonte
O ORM fornece uma abstração para que sua camada de dados seja independente de seu RDBMS, mas pode não ser suficiente para "desatar" a camada de negócios da camada de dados. Especificamente, você não deve permitir que objetos mapeados para tabelas RDBMS "vazem" diretamente na camada de negócios.
No mínimo, sua camada de negócios precisa programar para interfaces que seus objetos mapeados por tabela e gerenciados por ORM da camada de dados poderiam potencialmente implementar. Além disso, pode ser necessário criar uma camada baseada em interface da construção de consultas abstratas para ocultar os recursos de consulta nativos do seu ORM. O objetivo principal é evitar "inserir" qualquer ORM específico em sua solução além da camada de dados. Por exemplo, pode ser tentador criar seqüências de caracteres HQL ( Hibernate Query Language ) na camada de negócios. No entanto, essa decisão aparentemente inocente vincularia sua camada de negócios ao Hibernate, unindo as camadas de negócios e de acesso a dados; você deve tentar evitar essa situação o máximo possível.
EDIT: No seu caso, a camada adicional dentro do repositório é uma perda de tempo: com base no seu ponto número dois, sua camada de negócios é suficientemente isolada do seu repositório. O fornecimento de isolamento adicional introduziria complexidade desnecessária, sem benefícios adicionais.
O problema com a criação de uma camada extra de abstração dentro do seu repositório é que a "marca" específica do ORM determina a maneira como você interage com ele. Se você criar um invólucro fino que se pareça com o seu ORM, mas esteja sob seu controle, a substituição do ORM subjacente será mais ou menos tão difícil quanto seria sem essa camada adicional. Se, por outro lado, você criar uma camada que não se parece com o seu ORM, deverá questionar sua escolha da tecnologia de mapeamento objeto-relacional.
fonte
O UnitOfWork geralmente fornece essa abstração. É um lugar que precisa mudar, seus repositórios dependem dele por meio de uma interface. Se você precisar alterar o O / RM, basta implementar uma nova UoW sobre ele. Um e pronto.
BTW vai além de apenas trocar de O / RM, pense em testes de unidade. Eu tenho três implementações UnitOfWork, uma para EF, uma para NH (porque eu realmente precisei alternar O / RMs no meio do projeto para um cliente que desejava suporte Oracle) e uma para persistência do InMemory. A persistência do InMemory foi perfeita para testes de unidade ou mesmo para prototipagem rápida antes que eu estivesse pronto para colocar um banco de dados por trás dele.
A estrutura é simples de implementar. Primeiro você tem sua interface IRepository genérica
E a interface IUnitOfWork
Em seguida, é o repositório base (sua escolha é se deve ou não ser abstrato
Implementar o IUnitOfWork é uma brincadeira de criança para EF, NH e In Memory. O motivo pelo qual eu retornei o IQueryable é pelo mesmo motivo, Ayende mencionou em seu post, o cliente pode filtrar, classificar, agrupar e até mesmo projetar o resultado usando o LINQ e você ainda obtém o benefício de tudo ser feito no servidor.
fonte