Como devo implementar o padrão de repositório para modelos de objetos complexos?

21

Nosso modelo de dados possui quase 200 classes que podem ser separadas em cerca de uma dúzia de áreas funcionais. Teria sido bom usar domínios, mas a separação não é tão limpa e não podemos alterá-la.

Estamos redesenhando nosso DAL para usar o Entity Framework e a maioria das recomendações que eu vi sugerem o uso de um padrão de repositório. No entanto, nenhuma das amostras realmente lida com modelos de objetos complexos. Algumas implementações que encontrei sugerem o uso de um repositório por entidade. Isso parece ridículo e insustentável para modelos grandes e complexos.

É realmente necessário criar um UnitOfWork para cada operação e um Repositório para cada entidade? Eu poderia acabar com milhares de aulas. Sei que isso não é razoável, mas encontrei muito pouca orientação para implementar o Repositório, a Unidade de Trabalho e o Entity Framework sobre modelos complexos e aplicativos de negócios realistas.

Eric Falsken
fonte

Respostas:

6

Primeiro, você percorrerá todas as entidades que possui e se perguntará:

Faz sentido persistir sozinha nessa entidade?

O que quero dizer aqui é que, no seu modelo de objeto, algumas entidades provavelmente estão contidas em outras em um relacionamento de mestre-detalhe. Se sua entidade é altamente dependente de outra, não crie um repositório apenas para essa entidade, porque provavelmente não será persistido por si só. Em vez disso, você criará um repositório para cada classe pai e garantirá que as entidades filhas e outras relações sejam mantidas ao mesmo tempo.

Não gosto de como eles implementaram o padrão UnitOfWork no link que você forneceu. Eu sugiro que você faça algo mais nesse sentido . Você não precisa definir uma classe por repositório. A mesma classe pode ser usada para todos os repositórios, cada um com sua própria instância da classe UnitOfWork durante toda a vida útil da operação. Você também pode reutilizar o mesmo UnitOfWork em diferentes repositórios para as alterações que deseja que sejam mantidas ao mesmo tempo.

marco-fiset
fonte
Belo link! Estou checando.
Eric Falsken 17/10/12
Seu link (e resposta) foram os mais úteis, embora eu acabasse não usando os padrões fornecidos. Acabei usando uma classe de invólucro que aplicou um proxy nos métodos Add / Attach / Remove / SaveChanges para funcionar como um repositório genérico e adicionei um método Query / QuerySingle / QueryAll que aceita classes de consulta personalizadas para manter a implementação da minha consulta. Isso está funcionando muito bem, para que eu possa fazer consultas LINQ e T-SQL sem envolver a EF diretamente.
Eric Falsken 23/10/12
O Entity Framework, com o uso de transações, é uma implementação do padrão da Unidade de Trabalho.
precisa
1
link está morto ...
Newtopian
3

Talvez você deva dar uma olhada no Design Orientado a Domínio . Ele recomenda agrupar seus objetos em Agregados e criar repositórios apenas para a entidade Raiz de cada Agregado. É uma boa maneira de ordenar um modelo de objetos grande e complexo.

Suas diferentes áreas funcionais podem ser contextos limitados . Existem várias técnicas para lidar com contextos limitados sobrepostos, se a separação entre eles não for clara.

guillaume31
fonte
0

Que fundamento teórico você encontrou para o design de banco de dados "Padrão de repositório"? Eu estou supondo que nenhum. É uma camada de complexidade baseada em uma premissa falsa: que a "camada de persistência" é algo de que você precisa se isolar. Pelo que posso dizer, isso contribui para o desconhecimento generalizado da programação dos princípios de design relacional e favorece uma centralidade pressuposta do design de OO do aplicativo. Mas isso não justifica sua existência por razões racionais, muito menos teóricas.

O caminho verdadeiro para o design de banco de dados não mudou em 30 anos: analise os dados. Encontre as chaves, restrições e relacionamentos muitos-para-um. Crie suas tabelas de acordo com a forma normal do Boyce-Codd. Use visualizações e procedimentos armazenados para facilitar o acesso aos dados.

Por mais indesejável que seja, um DBMS do SQL fornece uma melhor camada de isolamento do que qualquer coisa que o programador possa fornecer. É verdade que, conforme o banco de dados muda, o SQL usado para acessar pode ter que mudar. Mas observe que isso é verdade, independentemente de haver ou não uma camada de mediação . Desde que o aplicativo use visualizações e procedimentos armazenados para acessar o DBMS, as ferramentas comuns de engenharia do SQL indicarão quando alterações no banco de dados subjacente invalidam essas visualizações e procedimentos armazenados.

Aí reside o desafio, é claro. Uma camada de mediação fornece a ilusão de isolamento e o conforto para o programador de escrever código, o que ele sabe fazer. Aprender o design do banco de dados e o SQL requer aprender algo novo. A maioria das pessoas prefere morrer a pensar e muitas têm sucesso.

Alguém da sua equipe sem dúvida objetará que escrever SQL para dar suporte às suas 200 aulas é muito trabalhoso. Sem dúvida. Mas pelo menos é um trabalho útil . Se você projetar um banco de dados imitando seu design de OO, também fará muito trabalho, grande parte inútil, e derrotará a maior parte do que o DBMS oferece a você.

Por exemplo, você considera refletir a Unidade de trabalho no banco de dados (como tabela ou tabelas, presumo). Unidade de trabalho é um built-in de serviço do DBMS: begin transaction... banco de dados de atualização ... commit transaction. Nada para modelar, além do mapeamento de suas classes para as tabelas de banco de dados no SQL.

Sua pergunta foi publicada há 4 anos. Estou respondendo porque foi "atualizado" de alguma forma recentemente, indicando que ainda interessa a alguém. Espero que minha resposta incentive o leitor a aplicar a teoria relacional básica ao problema, em vez de adotar uma solução inútil.

James K. Lowden
fonte