Вставить запись с помощью составного ключа с помощью NHibernate не удается - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь сослаться на некоторые дочерние объекты с частью составного идентификатора родителей. У меня есть таблица определений, приведенная ниже:

Programs
Events
ProgramEvents

Файлы классов:

public class Program
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<ProgramEvent> StartEvents { get; set; }
    public virtual IList<ProgramEvent> EndEvents { get; set; }
}

public class ProgramEvent
{
    public virtual Event Event { get; set; }
    public virtual bool Repeatable { get; set; }
    public virtual int EventOrder { get; set; }
    public virtual int EventSection { get; set; }
    public virtual Program Program { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as ProgramEvent);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = GetType().GetHashCode();

            hash = (hash * 31) ^ EventSection.GetHashCode();
            hash = (hash * 31) ^ EventOrder.GetHashCode();
            hash = (hash * 31) ^ Event.Id.GetHashCode();
            hash = (hash * 31) ^ Program.Id.GetHashCode();

            return hash;
        }
    }

Отображение для класса программы содержит такую ​​ссылку:

<list name="StartEvents" table="ProgramEvents" lazy="false" where="EVENT_SECTION = 1" cascade="all-delete-orphan" inverse="true">
  <key column="PROGRAM_ID" />
  <index column="EVENT_ORDER" />
  <one-to-many class="ProgramEvent"/>
</list>

Отображение для класса событий программы:

  <class name="ProgramEvent" table="ProgramEvents">

    <composite-id>
      <key-many-to-one class="Program"  lazy="false" name="Program" column="PROGRAM_ID" />
      <key-many-to-one class="Event"  lazy="false" name="Event" column="EVENT_ID" />
      <key-property name="EventOrder" column="EVENT_ORDER" />
      <key-property name="EventSection" column="EVENT_SECTION" />
    </composite-id>

    <property name="Repeatable" column="REPEATABLE"/>

  </class>

Когда я пытаюсь сохранить программу с новой ссылкой на таблицу событий, я получаю такую ​​ошибку:

SqlException: Невозможно вставить значение NULL в столбец 'PROGRAM_ID', таблица «ProgramEvents»; столбец не допускает пустых значений. Вставить не удается. Заявление было прекращено.

Я открываю sql profiler и получаю такой sql:

exec sp_executesql N'INSERT INTO ProgramEvents (REPEATABLE, PROGRAM_ID, EVENT_ID, EVENT_ORDER, EVENT_SECTION) VALUES (@ p0, @ p1, @ p2, @ p3, @ p4) ', N' @ p0 bit, @ p1 int, @ p2 int, @ p3 int, @ p4 INT», @ p0 = 1, @ p1 = NULL, @ p2 = NULL, @ p3 = 0, @ p4 = 0

NHibernate действительно пытается вставить нулевые значения. Почему это происходит?

UPD Я пытаюсь обновить программу так:

    var program = ProgramDao.Current.GetById(1);

    var newEvent = EventDao.Current.GetById(4);
    var programEvent = new ProgramEvent { Event = newEvent, Repeatable = true };
    program.StartEvents.Add(programEvent);

    using (var session = SessionFactory.Current.OpenSession())
    {
        session.Evict(program);
        session.Update(program);
        session.Flush();
    }

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Вы должны установить programEvent.Program, чтобы он указывал на программу. Поскольку вы указываете inverse = true, содержащийся класс отвечает за сохранение ссылки на Программу.

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

0 голосов
/ 18 сентября 2018

попробуйте этот код:

public class ClassNameMap: ClassMap<ClassName>
{
    public ClassNameMap()
    {
        CompositeId().
            .KeyReference(x => x.A, "A")
            .KeyReference(x => x.B, "B");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...