2012-03-05 4 views
0

Я пытаюсь создать тестовое приложение, которое отображает зависимости событий: т. Е. Результирующий граф зависимостей (в отличие от всего древовидного графика). Что-то вроде:Fluent Nhibernate От многих до многих отношений/Иерархия зависимостей

public class Event() { 
    public virtual int Id {get;set;} 
    public virtual IList<Event> Dependencies {get;set;} 
} 

Другое требование в том, что я смогу пересечь график в обоих направлениях: при любом одно событие, я могу получить доступ к его зависимости, а также его предпосылки, используя NHibernate.

Многие события могут зависеть от одного события, происходящего ... но и любое данное событие может зависеть от многих других событий. Какова должна быть модель (или для этого требуется более одной модели)? Как это можно сопоставить с помощью Fluent NHibernate? И есть ли конфигурация/сопоставление, которая защитит от циклических ссылок?

ответ

0

Мы делаем что-то похожее на это и способ его сопоставления в том, что зависимые События должны иметь столбец, который сопоставляется с родительским событием. Это создает необходимые отношения между родителями и дочерними элементами, которые необходимы для корректности отображения, и предотвращение какой-либо циклической ссылки. Мы перешли на NH 3.2 кодовыми отображений, так что моя свободно может быть немного дрянной, но Heres мое лучшее предположение:

public class EventMap : ClassMap<Event> 
{ 
    public EventMap() 
    { 
     //the normal ID and property stuff 

     References(x => x.ParentEvent).Column("ParentEventId"); 

     HasMany(x => x.Dependencies).KeyColumn("ParentEventId"); 
    } 
} 

Edit:

К сожалению - не видел, что вы хотели HasManyToMany. Это может выглядеть примерно так:

public class EventMap : ClassMap<Event> 
    { 
     public EventMap() 
     { 
      //the normal ID and property stuff 

      HasManyToMany(x => x.Dependencies).Table("EventDependentEvent").AsBag(); 
     } 
    } 

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

+0

Я дам это попробовать в ближайшее время ... получили другие пожары прямо сейчас. ;) – Handprint

+0

У меня возникло исключение FluentConfigurationException, связанное с дублированием Event_id. Добавлено .ChildKeyColumn ("TheEvent") перед .AsBag(). Будет держать вас в курсе, насколько работоспособным оказывается. – Handprint

+0

Да - в зависимости от установки идентификатора вам может потребоваться переопределить некоторые значения по умолчанию для столбцов. – Fourth

0

Решение, которое я закончил с (до сих пор) ...

В модели:

public virtual IList<Event> Dependencies{ get; set; } 
    public virtual IList<Event> Prerequisites{ get; set; } 

В Mapping:

 HasManyToMany(x => x.Dependencies) 
      .Table("Dependencies") 
      .ChildKeyColumn("Dependent"); 
     HasManyToMany(x => x.Prerequisites) 
      .Table("Prerequisites") 
      .ChildKeyColumn("Prerequisite"); 

И предотвратить круговыми рефов, глядя для ложных от:

private bool IsPrerequisiteEvent(Event dependent, Event prereq) 
    { 
     bool isPrereq = false; 
     if (prereq == null) 
      isPrereq = false; 
     else if (dependent.Id == prereq.Id) 
      isPrereq = true; 
     else 
     { 
      int i = 0; 
      while (!isPrereq && i < dependent.PrerequisiteEvents.Count) 
      { 
       isPrereq |= IsPrerequisiteEvent(dependent.PrerequisiteEvents[i], prereq); 
       i++; 
      } 
     } 
     return isPrereq; 
    } 

    private bool IsDependentEvent(Event prereq, Event dependent) 
    { 
     bool isDependent = false; 
     if (prereq == null) 
      isDependent = false; 
     else if (dependent.Id == prereq.Id) 
      isDependent = true; 
     else 
     { 
      int i = 0; 
      while (!isDependent && i < dependent.DependentEvents.Count) 
      { 
       isDependent |= IsDependentEvent(prereq, dependent.DependentEvents[i]); 
       i++; 
      } 
     } 
     return isDependent; 
    } 

Есть компромиссы к этому подходу: db IS denormalized, но мне не нужно создавать новый объект зависимостей и заполнять список зависимых/prereq билетов для каждого билета, а затем делать мои чеки. Кажется более простым в том, чтобы кодировать этот путь на данный момент. Открытые для предложений, хотя!

Смежные вопросы