Как работать с отношением «многие ко многим» в моем API - PullRequest
2 голосов
/ 22 ноября 2008

У меня есть две сущности Foo и Bar с отношениями между многими и многими.

Допустим, нет семантического аргумента о том, почему Foo может быть «ответственным» за отношение «многие ко многим», но мы произвольно решаем, что Foo отвечает за отношение (т. Е. В NHibernate мы помечаем Bar как Inverse)

Это все хорошо с точки зрения БД, но мои API-интерфейсы для сущностей показывают проблему.

    // 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
        }
    }

Если мы решили, что Foo несет ответственность за эти отношения, как мне обновить связанную коллекцию в Bar, не создавая общедоступный метод Bar.AddFoo (), который даже не должен существовать?

Мне кажется, что я должен быть в состоянии поддерживать целостность модели моего домена, не прибегая к необходимости перезагрузки этих объектов из БД после такой операции.

ОБНОВЛЕНИЕ: настройка кода, вдохновленная комментатором.

Ответы [ 4 ]

3 голосов
/ 22 ноября 2008

Возможно, вам не хватает концепции домена. Вы пытались создать третье лицо: FooBarRelationship?

2 голосов
/ 22 ноября 2008

См. Рабочие двунаправленные ссылки в документации по Hibernate.

Многие разработчики программы защищаются и создать методы управления ссылками для правильно установить обе стороны, например в Лицо:

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

Я лично считаю, что объект Entity, содержащий список связанных объектов, слишком умен, и вы должны позволить DAL попасть в базу данных.

DALFactory.FooAdapter.getBars(foo);
1 голос
/ 22 ноября 2008

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

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 голосов
/ 22 ноября 2008

Вы можете сделать это статичным

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

Не совсем идеальный, но он сам получает функцию от объекта

...