2009-03-24 3 views
1

Je suis relativement nouveau à NHibernate et j'ai rencontré un étrange problème d'enchaînement d'héritage avec mes classes de dépôt. J'ai utilisé Gabriel Schenker's FAQ comme référence, et suite à ses exemples, j'ai créé des interfaces pour définir des contrats pour les opérations DAO dans les classes "repository". Le schéma de données avec lequel je travaille est plutôt étendu, et après un petit moment, je me suis retrouvé à dupliquer beaucoup de code. Plus précisément, les méthodes Add, Update, Delete et "GetByID" étaient exactement les mêmes après avoir ajouté un paramètre générique "EntityType" à l'interface de base. Ainsi, par exemple, ce serait l'interface la plus fondamentale pour les opérations de dépôt:NHibernate - Est-il acceptable d'utiliser une base abstraite pour fournir des fonctionnalités au lieu d'une interface?

public interface IBasicRepository<EntityType> where EntityType : class 
{ 
    void Add(EntityType entity); 
    void Remove(EntityType entity); 
    void Update(EntityType entity); 
    EntityType GetByID<IDType>(IDType id); 
} 

Je vais parler de la méthode Add à partir de maintenant, par souci de concision. Avec le EntityType générique, les mises en œuvre étaient les mêmes:

public void Add(EntityType entity) 
{ 
    using (ISession session = NHUtility.OpenSession()) 
    { 
     using (ITransaction transaction = session.BeginTransaction()) 
     { 
      session.Save(entity); 
      transaction.Commit(); 
     } 
    } 
} 

De toute évidence, en tapant ce même corps de la méthode à plusieurs reprises (avec le léger changement de type) est non seulement gênant, il est une mauvaise conception dans mon livre. J'ai donc créé une classe de base abstraite que j'appellerai RepositoryBase qui fournit l'implémentation de Add(). Comme j'utilise un abstract au lieu d'une interface, je "casse la chaîne d'interface" pour les classes héritées de RepositoryBase et je suis obligé de faire abstraction de toute dérivation, même s'il semble plus "correct" d'utiliser une interface. En utilisant cet exemple petite entité merdique ....

public class Entity1 
{ 
    public Guid ID { get; set; } 
    public String Name { get; set; } 
} 

... on ne peut le faire ...

public interface IEntity1Repository : RepositoryBase<Entity1> 
{ 
    //Illegal!!!! Bad, naughty programmer! 
} 

... mais est très bien ....

public abstract class Entity1RepositoryBase : RepositoryBase<Entity1> 
{ 
    public abstract ICollection<Entity1> GetByName(string name); 
} 

Cela me dérange. Ça marche, mais ça me fait mal, d'autant que la chaîne d'héritage/implémentation avec ce schéma particulier pourrait aller très loin. Donc je suppose que mes questions sont:

  1. Est-ce que je suis juste stupide et anxieux de rétention à ce sujet?
  2. Y at-il un design différent/meilleur que je devrais regarder ici? J'ai regardé d'autres exemples (notamment Billy McCafferty's) et l'approche de Schenker semble la plus simple pour les novices NHibernating.

Merci d'avance.

+0

Je ne laisserais pas le dépôt soit responsable de la gestion des transactions et la session – Paco

Répondre

7

Une option pourrait être:

public interface IRepository<T> where T: class 
{ 
    void Add(T entity); 
    void Remove(T entity); 
    void Update(T entity); 
    T GetByID<IDType>(IDType id); 
} 

Avec une classe de base qui implémente cette interface. À savoir:

public abstract class RepositoryBase<T> : IRepository<T> where T: class 
{ 
    ... 
} 

qui est ensuite étendu pour chaque type d'entité si nécessaire:

public interface IProductRepository : IRepository<Product> 
{ 
    // Add extra methods 
} 

public class ProductRepository : RepositoryBase<Product>, IProductRepository 
{ 
    // Implement extra methods 
} 
+0

Eh oui, voilà. Merci de me démêler. Je me cognais la tête contre le clavier dans la confusion. –

Questions connexes