Pergunta

Estou tentando escrever meu Modelo de domínio o mais interessante possível. A única coisa que estou fazendo agora é marcar todas as propriedades e métodos virtual, como Nibernate exige isso para o carregamento preguiçoso.

No meu Conjunto do modelo de domínio Eu defino algumas interfaces de repositório:

public interface IRepository<TEntity> where TEntity : EntityBase {
    TEntity Get(int id);
    /* ... */
}
public interface IProductRepository : IRepository<Product> { ... }

Então eu tenho um conjunto de dados. Este fará referência ao Nibernate, ele conhece sua existência. Esta é a montagem que implementa essas interfaces repositivas:

public abstract class Repository<TEntity> : IRepository<TEntity> {
    public TEntity Get(ind id) { ... }
    /* ... */
}
public class ProductRepository : Repository<Product>, IProductRepository {
    /* ... */
}

e assim por diante.

Agora eu queria implementar uma funcionalidade de transação para meus repositórios. Para fazer isso, eu acrescentaria um BeginTransaction Método na minha interface irepositória. No entanto, não posso definir seu tipo de retorno como NHibernate.ITransaction, já que quero manter o modelo de persistência-ignorante do modelo de domínio e não ser forçado a fazer referência à Assembléia de Nhibernate da minha montagem do modelo de domínio.

O que você faria?

Você simplesmente implementaria um void BeginTransaction(), uma void Commit(), e a void RollBack() métodos na interface, e vamos A implementação do repositório gerencia o ITransaction objeto internamente?

Ou você encontraria uma maneira de exponha o ITransaction objeto Para deixar o cliente gerenciar a transação diretamente com ele, em vez de usar os métodos do repositório?

Obrigado!

Foi útil?

Solução

Você pode dar uma olhada no Arquitetura nítida que já implementou tudo o que você fala, incluindo repositórios genéricos com suporte para transações. A solução existe que o iRepository possui uma propriedade DBContext, que encapsula transações (na verdade é uma interface). Esta é a primeira das opções que você descreveu (interface de transações personalizadas que esconde o Nibernate). E funciona bem.

Eu acho que você pode até reutilizar o código S#ARP, independentemente de pretender usar a estrutura completa.

Outras dicas

As transações da IMO devem sempre começar e terminar na lógica de negócios; em outras palavras, a transação deve iniciar na camada de serviço, não a camada de repositório e o repositório deve se contratar na transação, idealmente isso seria feito implicitamente.

Agora, se você estiver usando o NH, se seu serviço e repositórios compartilharem a mesma 'sessão' (que eles deveriam), poderá chamar 'BeginTransaction' na camada de serviço e cometer ou reverter conforme necessário:

Por exemplo, imagine este um método em um serviço:

  public void RegisterCustomer(Customer customer)
    {
        try
        {
            using(var transaction = _session.BeginTransaction())
            {
                _customerRepository.Save(customer);
                _customerSurveyRepository.Save(customerSurvey);
                // DO What ever else you want...
                transaction.Commit();
            }
        }
        catch (Exception exn)
        {
            throw new AMException(FAILED_REGISTRATION, exn);
        }
     }

Como os repositórios obtêm uma referência à mesma sessão podem ser resolvidos injetando nos construtores ou usando a SessionFactory para obter a sessão atual ...

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