Подтвердить что ты не робот

Как смоделировать много ко многим отношениям в коде?

Предположим, что у меня есть две таблицы в базе данных. например: Dog and Boss Это отношения многих и многих, потому что у босса может быть более одной собаки, а у собаки может быть более 1 владельца. Я владелец Бобби, но так же и моя жена.

Но многим не разрешено, поэтому есть помощник: DogsPerBoss

Как смоделировать это в коде?

У класса Boss может быть коллекция собак. У собаки класса может быть коллекция боссов. - По крайней мере, это то, что я думаю. Возможно, есть лучшие решения?

Как насчет дополнительных данных, которые находятся в вспомогательной таблице? Должно ли это быть в классе Босса или в классе Dog? например: Псевдоним (Я называю собаку "хорошим мальчиком", и моя жена называет его "собачкой" )

Надеюсь, мой вопрос будет ясным? Есть ли какие-либо лучшие практики в отношении того, что является лучшим способом достичь этого? Можете ли вы дать мне несколько ссылок?

ORM (например, NHibernate) не является вариантом.

4b9b3361

Ответ 1

Почему вы говорите о таблицах? Вы создаете объектную модель или модель базы данных?

Для объектной модели нет причин, по которым у собаки не может быть List<Owner>, а у владельца есть List<Dog>. Только если у вас есть атрибуты отношения, вам нужен промежуточный класс (что UML вызывает Class Association). Это, когда у вас будет класс DogOwnership с дополнительными свойствами, и каждый владелец будет иметь List<DogOwnership>, и каждая из них будет. У DogOwner есть Собака, Владелец и дополнительные свойства.

Ответ 2

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); } }
}

Вышеупомянутое утверждает, что отношения Боссов могут иметь несколько собак (с применяемым пределом) и собак, имеющих несколько боссов. Это также означает, что, когда босс добавляет собаку, они могут указать псевдоним для собаки, которая уникальна только для этого босса. Это означает, что другие боссы могут добавлять одну и ту же собаку, но с разными прозвищами.

Что касается ограничения, я бы, вероятно, имел бы это как значение App.Config, которое вы только что прочитали, прежде чем создавать экземпляр объекта (ов) босса. Таким образом, небольшой пример:

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.

Вы можете, очевидно, настроить это, как вы сочтете нужным, однако я думаю, что основы того, что вы ищете, есть.

  • Босс может иметь несколько собак с ограничением
  • Собаки могут иметь несколько боссов.
  • У боссов могут быть разные псевдонимы для той же собаки.

Ответ 3

Что-то вроде этого; Он все еще нуждается в некоторой финализации (сделайте коллекцию закрытой и добавьте для нее общедоступный общедоступный аксессор, который, например, возвращает readonlycollection, но вы поймаете дрейф.

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);
        }
    }
}

Таким образом, вы можете смоделировать много ко многим в своем коде, где каждая Собака знает своих Боссов, и каждый Босс знает своих Собаков. Когда вам нужны дополнительные данные в таблице помощников, вам также нужно создать еще один класс.

Ответ 4

Если вам не нужно записывать ник, то у собаки должен быть список боссов, а у босса должен быть список собак.

Если отношение между Dog и Boss имеет атрибуты, в этом случае псевдоним, тогда вы должны создать класс для представления этого отношения, а Dog и Boss будут содержать списки этого типа.

Я использовал NHibernate некоторое время и считаю это очень полезным для облегчения такого рода несоответствие реляционного импеданса объекта.

Ответ 5

Это классическая проблема между базами данных, где многие из многих не работают, следовательно, ваша вспомогательная таблица и мир объектов, где многие многие работают нормально. Как только отношение имеет атрибуты, вы должны создать новый класс для хранения этой информации. Тем не менее, вы сэкономите себе много времени на голову, если вы посмотрите на Object Relation Mapping - ORM - все это поле выросло для решения этой (и многих других) проблем между DB и Object.

Ответ 6

Если у вас есть простая таблица ссылок "многие-ко-многим" с внешними ключами из каждой таблицы в отношениях, то вы бы ее моделировали, как вы предлагаете: у Босса есть коллекция собак, а у собаки есть коллекция боссов.

Если у вас есть отношение "многие ко многим" с дополнительными данными, такими как "Никнейм", тогда вы должны моделировать это как два отношения "один ко многим". Создайте сущность, такую ​​как DogBoss, чтобы у Босса была коллекция DogBoss, а у собаки есть коллекция DogBoss.

Ответ 7

традиционное отношение многих ко многим не будет иметь дополнительных полей в таблице соответствия.

Поскольку у вас есть поля с уникальной информацией, я склонен перестать думать об этих отношениях как многие ко многим.

Как только вы добавите информацию в соответствующую таблицу, я думаю, что вы сделали эту таблицу в отдельную сущность и поэтому ей нужен ее собственный объект.

На этом этапе вы можете начать использовать класс DogsName для подключения человека и собаки - оба из которых будут содержать ссылки на этот объект как часть коллекции.

Однако, независимо от того, даете ли вы собаке имя, которое вызывается или владеете собакой, являются независимыми.

Также, как и моделирование отношения имен собак в зависимости от разных людей, вам также необходимо смоделировать отношения собственности. В памяти это означает, что оба объекта содержат список других объектов.

Ответ 8

Я, кажется, что-то упускаю. Почему многим не разрешено?

public class Boss
{
    Dog[] dogs;
}

public class Dog
{
    Boss[] bosses;
}

Ответ 9

В реляционной модели лучший способ моделирования отношения многих к многим (используя ваш пример Dogs/Bosses) состоит в том, чтобы иметь три отдельные таблицы.

Одна таблица для DOGS, одна таблица для BOSSES (и каждая из этих таблиц имеет уникальный ключ), а третья таблица обычно представляет собой таблицу ".

В этой таблице обычно есть как минимум два поля, одно поле для внешнего ключа для собаки и другое поле для внешнего ключа Boss. Таким образом, у каждой собаки может быть много боссов, и у каждого босса может быть много собак.

Теперь, когда дело доходит до моделирования этого кода более объектно-ориентированным образом, это обычно достигается с помощью класса Dog и класса Boss. Как и обычные свойства атомов для каждого из этих объектов, каждый из них также выставляем свойство, которое является коллекцией другого.

Итак, например, объект Dog будет иметь свойство "Bosses". Это свойство будет отображать коллекцию объектов Boss, которые выделяются конкретному объекту Dog (как определено в таблице соединений), а с другой стороны каждый объект Boss будет выставлять свойство Dogs, которое будет представлять собой набор объектов Dog к этому конкретному объекту Boss (как определено таблицей соединения).

Обратите внимание, что в этих объектах может быть какое-то "перекрытие" (т.е. один "собачий" объект может иметь объекты "босса", которые есть у другого "собачьего объекта" ), однако это традиционный механизм для перевода трехмерного объекта, таблицу реляционной модели "многие ко многим" в объектно-ориентированную.

Ответ 10

Я пропустил что-то или это единственный код, который вам нужен для этого, следующим образом:

List<Bosses> BossList;

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

Вам не нужно явно моделировать двусторонние отношения. Это подразумевается в структуре кода. Могут быть и другие причины для этого, но в целом достаточно иметь одностороннюю ссылку и способ пересечения множества объектов-ссылок.

Ответ 11

Каждый раз, когда нам нужно думать о реальной жизни и наших потребностях. В этом случае ключевым моментом является то, что нужно иметь другой.

В реальной жизни собака и босс могут не иметь друг друга. Но ваши потребности в программном обеспечении должны влиять на эти отношения.

  • Например, если вы разрабатываете программное обеспечение для управления ветеринарными пациентами, для ветеринара, который лечит бродячих собак, тогда отношения пациента (собаки) -Guardian (босса) должны быть такими: Боссы должны иметь хотя бы одну собаку, а собака может не иметь какого-либо босса (тогда босс-идентификатор является внешним ключом этих отношений), что означает, что в вашем дизайне класс собаки должен содержать коллекцию боссов. Почему, потому что любой экземпляр босса не может быть создан без какой-либо собаки (ов). Мы также можем принять это решение с логикой данных. Давайте подумаем, когда вы пытаетесь сохранить свои классы собак и боссов в базе данных. Если условие отношения, как указано выше, при сохранении босса, вы должны вставить запись о соединении в таблицу соединений.

  • Если вы разрабатываете это программное обеспечение ветеринаром, который не лечит бродячих собак, то отношения пациента с родителями должны быть такими: У собаки должен быть хотя бы один босс, а босс должен иметь хотя бы собаку, и нам нужно рассмотреть этот случай особых отношений. Это означает, что любой из этих экземпляров классов не может быть создан без eachother. Поэтому нам нужно определить эту специальность в нашей OO-дизайне. Это означает, что нам нужен класс, который представляет эту зависимость. Конечно, эта зависимость будет храниться в таблице соединений.

-Если ваше программное обеспечение разработано для ветеринара, который лечит бродячих собак и этих собак, принятых боссами, ваш дизайн должен быть таким:  Любая собака может не иметь босса (ов), и любой босс может не иметь собаку (ов) до принятия. В этом случае наш дизайн OO должен заботиться об этом специальном случае. Этот случай немного похож на первый. Поэтому мы можем добавить коллекцию любого класса в другую. Но любое программное обеспечение, подобное этому, будет влиять на другие потребности. Как отчет. Если ветеринар беспокоится о собаках, которые усыновлены боссом, рано или поздно он спрашивает сообщение, которое собака усыновила кем. Как и в предложении (собаки, принятые боссами), лучше, если класс собаки содержит коллекцию классов босса.

Надеюсь, я смогу дать правильные ответы на ваш вопрос.

Ответ 12

Не уверен, что вы просите. Но это структура таблицы, которую вы хотите:

Таблица собак

DOG_ID int PK DOG_Name varchar (50)

DogsPerBoss

ID int DOG_ID int BOSS_ID int DogNickName varchar (15)

Boss

BOSS_ID int PK BOSS_Name varchar (50)