2008-11-22 19 views
2

J'ai deux entités Foo et Bar avec une relation de plusieurs à plusieurs entre eux. Supposons qu'il n'y ait pas d'argument sémantique pour expliquer pourquoi Foo pourrait être «responsable» de la relation plusieurs à plusieurs, mais nous décidons arbitrairement que Foo est responsable de la relation (ie, dans NHibernate, nous marquerions Bar comme Inverse)Comment faire face à une relation Many-To-Many dans mon API

Tout va bien du point de vue de la base de données, mais mes API d'entité révèlent un problème.

// Responsible for the relation 
    public class Foo 
    { 
     List<Bar> Bars = new List<Bar>(); 

     public void AddBar(Bar bar) 
     { 
      Bars.Add(bar); 
      bar.AddFoo(this); 
     } 
    } 

    public class Bar 
    { 
     List<Foo> Foos = new List<Foo>(); 

     // This shouldn't exist. 
     public void AddFoo(Foo foo) 
     { 
      Foos.Add(foo); 
      foo.AddBar(this); // Inf Recursion 
     } 
    } 

Si nous avons décidé que Foo est responsable de cette relation, comment puis-je mettre à jour la collection associée à Bar sans créer une méthode Bar.AddFoo publique() qui devrait même pas exister?

Je pense que je devrais être en mesure de maintenir l'intégrité de mon modèle de domaine sans avoir à recharger ces entités à partir de la base de données après une opération comme celle-ci.

MISE À JOUR: Code tweak inspiré par le commentateur.

Répondre

1

Vous avez dit qu'un côté "possédera" la relation. Rendre cette méthode publique. Les autres associations (ou méthodes d'ajout) peuvent être rendues internes pour éviter que les consommateurs interagissent directement avec eux.

public class Foo 
{ 
    private IList<Bar> Bars {get;set;} 

    public void AddBar(Bar bar) 
    { 
     Bars.Add(bar); 
     bar.Foos.Add(this); 
    } 
} 

public class Bar 
{ 
    internal IList<Foo> Foos {get;set;} 
} 
+0

en fait, si Foo doit être public pour que les consommateurs puissent l'utiliser, alors l'exposer comme une collection immuable et utiliser la méthode AddFoo(). –

+0

Mes collections sont immuables, je ne voulais pas m'embêter avec tout ce gâchis dans l'exemple. Je suis retourné et en utilisant interne pour nettoyer certains domaine, je pense que cela a vraiment aidé ... Nous verrons comment cela fonctionne. –

-1

vous pouvez le rendre statique

public class Foo 
{ 
    List<Bar> Bars = new List<Bar>(); 

    public void AddBar(Bar bar) 
    { 
     Bars.Add(bar); 
     Bar.AddFoo(bar,this); 
    } 
} 

public class Bar 
{ 
    List<Foo> Foos = new List<Foo>(); 

    // This shouldn't exist. 
    public static void AddFoo(Bar bar, Foo foo) 
    { 
     bar.Foos.Add(foo); 
     //foo.AddBar(this); inf recurtion 
    } 
} 

Pas vraiment idéal mais il ne se la fonction de l'objet de son auto

2

Voir Working bi-directional links dans la documentation Hibernate.

programme De nombreux développeurs défensivement et créer des méthodes de gestion de liaison à correctement définies des deux côtés, par exemple en Personne:

protected Set getEvents() { 
    return events; 
} 

protected void setEvents(Set events) { 
    this.events = events; 
} 

public void addToEvent(Event event) { 
    this.getEvents().add(event); 
    event.getParticipants().add(this); 
} 

public void removeFromEvent(Event event) { 
    this.getEvents().remove(event); 
    event.getParticipants().remove(this); 
} 

Je pense personnellement objet entité qui détient la liste des objets est d'être trop lié à puce, et vous devriez laisser le DAL a frappé la base de données.

DALFactory.FooAdapter.getBars(foo); 
3

Il se peut qu'un concept de domaine vous manque. Avez-vous essayé de créer une troisième entité: FooBarRelationship?

+0

parfois cela est approprié, d'autres fois trop. NH vous permettra de stocker des données de base pour capturer la relation, même sans créer une autre entité. +1 pour la suggestion cependant. –

+0

Si j'avais d'autres informations à faire glisser avec la relation, je pourrais faire exactement cela, mais pour le moment j'hésite à ajouter cela parce que je n'ai pas de telles informations supplémentaires. –