Pergunta

Eu estou olhando para ver o que aproxima as pessoas poderiam ter levado para detectar mudanças em entidades que fazem parte de seus agregados. Eu tenho algo que funciona, mas eu não sou louco por ela. Basicamente, meu repositório é responsável por determinar se o estado de uma raiz agregada mudou. Vamos supor que eu tenho uma raiz agregada chamado Book e uma entidade chamada Page dentro do agregado. A Book contém uma ou mais entidades Page, armazenados em uma coleção Pages.

Primeiramente, insira cenários de actualização vs. são feitas por inspecionar a raiz agregado e das suas entidades para determinar a presença de uma chave. Se a chave estiver presente, presume-se que o objeto tenha sido, de uma só vez, salvo para a fonte de dados subjacente. Isto o torna um candidato para uma atualização; mas não é definitiva com base nessa sozinho para as entidades. Com a raiz agregada a resposta é óbvia, uma vez que há apenas um e é o ponto singular de entrada, pode-se supor que a presença chave ditará a operação. É um cenário aceitável, no meu caso, para salvar a própria raiz agregada de volta para que eu possa capturar uma data de modificação.

Para ajudar a facilitar esse comportamento para as entidades si, minha classe EntityBase contém duas propriedades simples: IsUpdated(), IsDeleted(). Ambos padrão para false. Eu não preciso saber se ele é novo ou não, porque eu posso fazer essa determinação baseia-se na presença da chave, como mencionado anteriormente. Os métodos para a aplicação, neste caso a Página, teria cada método que muda a IsUpdated() apoio conjunto de dados para true.

Assim, por exemplo, Página tem um método chamado UpdateSectionName() que altera o valor apoio da propriedade SectionName, que é somente leitura. Esta abordagem é utilizada de forma consistente, uma vez que permite a um ponto de fixação lógico de validadores no método (impedindo a entidade de entrar num estado inválido) que executa a configuração de dados. O resultado final é que eu tenho que colocar um this.IsUpdated() = true; no final do método.

Quando a raiz agregada é enviado para o repositório para o Save() (um interruptor lógica para tanto uma operação Insert() ou Update()), pode então iterar sobre a coleção Pages na Book, olhando para todas as páginas que têm um dos três cenários :

  1. Nenhuma chave. será inserido um Page sem chave.
  2. IsDeleted = true; uma exclusão trunfos de uma atualização, e a exclusão serão cometidos -. Ignorando qualquer actualização para o Page
  3. IsUpdated = true; Uma atualização estará empenhada para a página.

Fazendo dessa forma, impede-me de apenas cega atualizando tudo o que está na coleção Pages, que poderia ser assustador se não houvesse centenas de entidades página no livro, por exemplo. Eu tinha vindo a considerar a recuperação de um exemplar do Livro, e fazendo uma comparação e apenas mudanças cometendo detectado, (inserções, atualizações e exclusões com base na presença e / ou comparação), mas parecia ser uma maneira muito falador ir sobre ele .

A principal desvantagem é que o desenvolvedor tem que lembrar de configurar IsUpdated em cada método na entidade. Esqueça um, e não vai ser capaz de detectar mudanças para esse valor. Eu brinquei com a idéia de algum tipo de armazenamento de backup personalizado que poderia transparente mudanças timestamp, o que poderia, por sua vez make IsUpdated uma propriedade somente leitura que o repositório poderia usar para atualizações agregadas.

O repositório está usando uma unidade de implementação padrão de trabalho que está baseando suas ações na timestamp gerado quando a raiz agregado foi adicionado a ele. Desde que pode haver várias entidades na fila para operações, operações entidade são enroladas e executado Immemente após a operação de raiz agregado (s) são executados que as entidades pertencem. Eu podia ver a tomar um passo adiante e criar uma outra unidade de trabalho para apenas lidar com as operações da entidade e base-los algum tipo de acompanhamento de eventos usado na entidade (que é como eu estou supondo que alguns dos produtos ORM no mercado realizar um nível semelhante de funcionalidade).

Antes de eu continuar se movendo nesta direção, porém, eu gostaria de ouvir ideias / recomendações / experiências sobre esta questão.

Editar: Algumas peças adicionais de informações que podem ser úteis a saber:

  1. A linguagem atual que eu estou trabalhando com é C #, embora eu tentei manter o máximo de informações de idioma específico como possível, porque esta é mais uma discussão teórica.
  2. O código para os repositórios / serviços / entidades / etc. é baseado em conceito de Tim McCarthy em seu livro, ".NET Domínio-Driven Design with C #" eo código de suporte no CodePlex . Ele fornece uma compreensão executável do tipo de abordagem, embora o que eu estou trabalhando com grande parte foi reescrita a partir do zero.
Foi útil?

Solução

Em suma, a minha resposta é que eu fui com o que eu propus. Ele está trabalhando, mas estou certo de que há espaço para melhorias. As mudanças realmente teve muito pouco tempo, então eu sinto que não fiz navegar muito longe do beijo ou diretores YAGNI neste caso. : -)

Eu ainda sinto que há espaço para cronometrar as questões relacionadas com as operações, mas deve ser capaz de trabalhar em torno deles nas implementações do repositório. Não é a solução ideal, mas não estou certo de que vale a pena reinventar a roda para corrigir um problema que pode ser evitado em menos tempo do que leva a correção.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top