¿Cómo modelar una relación de muchos a muchos en código?


Supongamos que tengo 2 tablas en una base de datos. por ejemplo: Perro y Jefe Esta es una relación de muchos a muchos, causa un jefe puede tener más de 1 perro, y el perro puede tener más de 1 propietario. Soy el dueño de Bobby, pero también lo es mi esposa.

Pero muchos a muchos no está permitido, por lo que hay un helpertable: DogsPerBoss

¿Cómo modelar esto en código?

El Jefe de clase puede tener una colección de Perros. Class Dog puede tener una colección de Jefes. -- >al menos, eso es lo que pienso. Tal vez hay mejores soluciones?

¿Qué hay de los datos adicionales que están en la tabla helper? ¿Debería ser en la clase de Jefe o en la clase de Perro? por ejemplo: Apodo (Yo llamo al perro "buen chico" y mi esposa lo llama "perrito")

Espero que mi pregunta sea un poco clara? ¿Existen buenas prácticas sobre cuál es la mejor manera de lograrlo? ¿Puedes darme algunas referencias?

Un OR (como NHibernate) no es una opción.

Author: John Saunders, 2009-07-09

12 answers

¿Por qué estás hablando de mesas? ¿Está creando un modelo de objetos o un modelo de base de datos?

Para un modelo de objetos, no hay razón para que un Perro no pueda tener un List<Owner> y un propietario tenga un List<Dog>. Solo si tiene atributos en la relación necesita una clase intermedia (lo que UML llama una Clase de Asociación). Es entonces cuando usted tendría una clase de propiedad de perros con propiedades adicionales, y cada Propietario tendría un List<DogOwnership>, y también lo haría cada Perro. El dueño del perro tendría un Perro, un Dueño, y el extra propiedad.

 21
Author: John Saunders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-16 21:06:49
public class Boss
{
   private string name;
   private List<Hashtable> dogs;
   private int limit;

   public Boss(string name, int dogLimit)
   {
      this.name = name;
      this.dogs = new List<Hashtable>();
      this.limit = dogLimit; 
   }

   public string Name { get { return this.name; } }

   public void AddDog(string nickname, Dog dog)
   {
      if (!this.dogs.Contains(nickname) && !this.dogs.Count == limit)
      {
         this.dogs.Add(nickname, dog);
         dog.AddBoss(this);
      } 
   }

   public void RemoveDog(string nickname)
   {
       this.dogs.Remove(nickname);
       dog.RemoveBoss(this);
   }

   public void Hashtable Dogs { get { return this.dogs; } }
}

public class Dog
{
   private string name;
   private List<Boss> bosses;

   public Dog(string name)
   {
      this.name = name;
      this.bosses = new List<Boss>();
   }

   public string Name { get { return this.name; } }

   public void AddBoss(Boss boss)
   {
      if (!this.bosses.Contains(boss))
      {
          this.bosses.Add(boss);
      }
   }

   public void RemoveBoss(Boss boss)
   {
      this.bosses.Remove(boss);
   }  

   public ReadOnlyCollection<Boss> Bosses { get { return new ReadOnlyCollection<Boss>(this.bosses); } }
}

Lo anterior mantiene la relación de Jefes puede tener varios perros (con un límite aplicado) y perros que tienen varios jefes. También significa que cuando un jefe está agregando un perro, puede especificar un apodo para el perro que es único para ese jefe solamente. Lo que significa que otros jefes pueden agregar el mismo perro, pero con apodos diferentes.

En cuanto al límite, probablemente tendría esto como una aplicación.Valor de configuración que acaba de leer antes de crear una instancia de los objetos boss. Así que un pequeño el ejemplo sería:

var james = new Boss("James", ConfigurationManager.AppSettings["DogsPerBoss"]);
var joe = new Boss("Joe", ConfigurationManager.AppSettings["DogsPerBoss"]);

var benji = new Dog("Benji");
var pooch = new Dog("Pooch");

james.AddDog("Good boy", benji);
joe.AddDog("Doggy", benji);

james.AddDog("Rover", pooch);
joe.AddDog("Buddy", pooch);  // won't add as the preset limit has been reached.

Obviamente puedes modificar esto como mejor te parezca, sin embargo, creo que los fundamentos de lo que estás buscando están ahí.

  • Boss puede tener varios perros con límite
  • Los perros pueden tener múltiples jefes
  • Los jefes pueden tener diferentes apodos para el mismo perro.
 13
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-17 09:01:55

Algo como esto; Sin embargo, todavía necesita un poco de ajuste (haga que la colección sea privada y agregue un accessor de readonly public para ella que devuelva una readonlycollection, por ejemplo, pero atrapará la deriva.

public class Dog
{
    public List<Boss> Bosses;

    public void AddBoss( Boss b )  
    {
        if( b != null && Bosses.Contains (b) == false )
        {
            Bosses.Add (b);
            b.AddDog (this);
        }
    }

    public void RemoveBoss( Boss b )
    {
         if( b !=null && Bosses.Contains (b) )
         {
             Bosses.Remove (b);
             b.RemoveDog (this);
         }
    }
}

public class Boss
{
    public List<Dog> Dogs;

    public void AddDog( Dog d )
    {
         if( d != null && Dogs.Contains (d) == false )
         {
              Dogs.Add(d);
              d.AddBoss(this);
         }
    }

    public void RemoveDog( Dog d )
    {
        if( d != null && Dogs.Contains(d) )
        {
            Dogs.Remove (d);
            d.RemoveBoss(this);
        }
    }
}

De esta manera, usted podría modelar un muchos a muchos en su código donde cada Perro conoce a sus Jefes, y cada Jefe conoce a sus Perros. Cuando necesite datos adicionales en la tabla auxiliar, también necesitará crear otra clase.

 5
Author: Frederik Gheysels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:16:40

Este es un problema clásico entre las bases de datos donde muchos a muchos no funcionan, de ahí su tabla de ayuda, y el mundo de objetos donde muchos a muchos funciona bien. Tan pronto como la relación tenga atributos, debe crear una nueva clase para contener esa información. Sin embargo, se ahorrará mucho tiempo si observa el Mapeo de relaciones de objetos - OR - todo ese campo creció para resolver este (y muchos otros) problemas entre la base de datos y el Objeto.

 1
Author: MrTelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:05:06

Si tiene una tabla de enlace simple de muchos a muchos con claves foráneas de cada tabla en la relación, entonces la modelaría como sugiere: Boss tiene una colección de Perros y Dog tiene una colección de Jefes.

Si tiene una relación de muchos a muchos con datos adicionales, como Nickname, entonces lo modelaría como dos relaciones de uno a muchos. Crea una entidad, como DogBoss para que Boss tenga una colección de DogBoss y Dog tenga una colección de DogBoss.

 1
Author: Jamie Ide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:05:25

La relación tradicional de muchos a muchos no tendría campos adicionales en la tabla correspondiente.

Debido a que usted tiene campos con información única tiendo a dejar de pensar en estas relaciones como muchos a muchos.

Una vez que agrega información a la tabla coincidente, creo que ha convertido esta tabla en una entidad por derecho propio y, por lo tanto, necesita su propio objeto para representarla.

En este punto puede comenzar a tener una clase DogsName para conectar una persona y un perro, ambos de que contendría referencias a este objeto como parte de una colección.

Sin embargo, si usted le da al perro un nombre para ser llamado por o propio del perro son independientes.

Además de modelar la relación del nombre de los perros de acuerdo con diferentes personas, también debe modelar las relaciones de propiedad. En memoria esto significaría que ambos objetos contienen una lista de los otros objetos.

 1
Author: John Nicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:06:24

Si no necesitabas grabar el apodo, entonces Dog debería tener una lista de Jefes y Boss debería tener una lista de Perros.

Si la relación entre Dog y Boss tiene atributos, en este caso nickname, entonces debe crear una clase para representar esa relación y hacer que Dog y Boss tengan listas de ese tipo.

He estado usando NHibernate desde hace un tiempo y lo encuentro muy útil para aliviar este tipo de desajuste de impedancia relacional de objetos .

 1
Author: Graham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:34:11

Supongo que me falta algo. ¿Por qué muchos a muchos no están permitidos?

public class Boss
{
    Dog[] dogs;
}

public class Dog
{
    Boss[] bosses;
}
 0
Author: Greg Dean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:03:18

En un modelo relacional, la mejor manera de modelar una relación de muchos a muchos (usando su ejemplo de Perros/Jefes) es tener tres tablas separadas.

Una tabla para PERROS, una tabla para JEFES (y cada una de estas tablas tiene una clave única), y la tercera tabla es generalmente una " tabla de unión".

Esta tabla normalmente tendrá al menos dos campos, un campo para la clave foránea de un Perro y el otro campo para la clave foránea de un Jefe. De esta manera cada perro puede tener muchos jefes, y cada Jefe puede tener muchos perros.

Ahora, cuando se trata de modelar esto en código de una manera más orientada a objetos, esto generalmente se logra teniendo una clase Dog y una clase Boss. Además de tener las propiedades atómicas habituales para cada uno de estos objetos, cada uno también exponer una propiedad que es una colección de la otra.

Así, por ejemplo, un objeto Dog tendría una propiedad llamada "Bosses". Esta propiedad expondría una colección de objetos Boss que están asignados al objeto Dog específico (como se define en la tabla junction), y en el otro lado, cada objeto Boss expondría una propiedad llamada Dogs que sería una colección de objetos Dog asignados a ese objeto Boss específico (como se define en la tabla junction).

Tenga en cuenta que bien puede haber alguna "superposición" en estos objetos (es decir, un objeto "perro" puede tener objetos "jefe" que otro objeto "perro" tiene), sin embargo, este es el mecanismo tradicional para traducir una tabla de tres muchos a muchos modelo relacional en uno orientado a objetos.

 0
Author: CraigTP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:08:51

¿Me falta algo o es el único código que necesita para esto de la siguiente manera:

List<Bosses> BossList;

class Dog {}
class Boss { Dog[] Dogs; }

No es necesario modelar explícitamente la relación bidireccional. Está implícito en la estructura del código. Puede haber otras razones para hacerlo, pero en general es suficiente tener una referencia unidireccional y una forma de atravesar el conjunto de objetos de referencia.

 0
Author: Mike Burton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:30:03

Cada vez que necesitamos pensar en la vida real y nuestras necesidades. En este caso, el punto clave es cuál debe tener otro.

En la vida real un perro y un jefe pueden no tener el uno al otro. Pero sus necesidades de software deberían afectar esta relación.

  • Por ejemplo, si está desarrollando un software de gestión de pacientes veterinarios, para un veterinario que cura perros callejeros, la relación Paciente(perro)-Tutor(jefe) debe ser así : Los jefes deben tener al menos un perro y el perro puede no tener ningún jefe (entonces el id del jefe es la clave externa de esta relación), lo que significa que en su diseño la clase de perro debe tener una colección de jefes. ¿Por qué porque cualquier instancia de jefe no se puede crear sin ningún perro(s). Podemos obtener esta decisión con la lógica de datos también. Vamos a pensar en cuando usted está tratando de salvar a su perro y clases jefe en la base de datos. Si la condición de relación como la anterior, mientras guarda un jefe debe insertar un registro de unión en la unión tabla.

  • Si está desarrollando ese software un veterinario que no cura perros callejeros, entonces la relación Paciente-Padre debe ser así: Un perro debe tener al menos un jefe y el jefe debe tener al menos un perro, y tenemos que considerar este caso de relación especial. Eso significa que cualquiera de estas instancias de clases no se pueden crear sin una sola. Así que necesitamos definir esta especialidad en nuestro diseño OO. Eso significa que necesitamos una clase que represente esta dependencia. Por supuesto esto la dependencia se almacenará en la tabla junction.

- Si su software desarrollado para un veterinario que cura perros callejeros y estos perros adoptados por los jefes de su diseño debe ser así: Cualquier perro puede no tener jefe (es) y cualquier jefe puede no tener ningún perro(s) hasta la adopción. En este caso, nuestro diseño OO debe preocuparse por este caso especial. Este caso un poco igual que el primero. Así que podemos añadir colección de cualquier clase en otra. Pero, cualquier necesidad de software como este afectará otras necesidades. Como informar. Si el veterinario se preocupa por los perros adoptados por el(los) jefe (es), tarde o temprano le pide un informe de qué perro adoptado por la oms. Al igual que en la frase, (perros adoptados por el jefe(es)) es mejor si la clase de perro contiene una colección de clases de jefe.

Espero poder dar respuestas adecuadas a su pregunta.

 0
Author: Murat YILMAZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-06 03:16:02

No estoy seguro de lo que estás pidiendo. Pero esta es la estructura de tabla que desea:

Tabla del perro

DOG_ID int PK Nombre del perro varchar (50)

DogsPerBoss

ID int DOG_ID int BOSS_ID int Nombre de perro varchar(15)

Jefe

BOSS_ID int PK BOSS_Name varchar (50)

 -1
Author: waqasahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-09 13:02:49