Явное значение для ошибки столбца идентификатора при вставке с отношением nHibernate - PullRequest
1 голос
/ 28 марта 2012

У меня есть 2 сущности NHibernate (таблицы), которые находятся в отношении один ко многим.

Я получаю эту ошибку:

Невозможно вставить явное значение для столбца идентификации в таблице'Bookings_Locations', когда для IDENTITY_INSERT установлено значение OFF.

при попытке сохранить (вставить) новые записи.

The error (easier to see if you open image in new tab)

Сущности

public class Booking
{
    public virtual int Id { get; set; }

    public virtual void AddBookingLocation(BookingLocation bookingLocationToAdd)
    {
        bookingLocationToAdd.Booking = this;
        this.BookingLocations.Add(bookingLocationToAdd);
    }

    public virtual void RemoveBookingLocation(BookingLocation bookingLocationToRemove)
    {
        this.BookingLocations.Remove(bookingLocationToRemove);
    }

    public virtual IList<BookingLocation> BookingLocations { get; set; }

    public Booking()
    {
        BookingLocations = new List<BookingLocation>();
    }
}

public BookingMap()
{
    Table("Bookings");

    Id(x => x.Id).Column("ID");
    HasMany(x => x.BookingLocations)
       .KeyColumn("ID")
      .Not.LazyLoad().Cascade.All(); 
}

public class BookingLocation
{
    public virtual int Id { get; set; }
    public virtual Booking Booking { get; set; }
}

public BookingLocationMap()
{
    Table("Bookings_Locations");    

    Id(x => x.Id).Column("ID");

    References(x => x.Booking)             
      .Column("ID")             
      .Not.LazyLoad().Nullable()
      .Cascade.All();
}

Значение первичного ключа BookingLocation (ID) равно 0, как только оно инициализировано, и я ничего ему не назначаю.Что приводит меня к мысли, что проблема как-то связана с картированием отношений.

Я делаю это перед вызовом метода на скриншоте:

Booking.AddBookingLocation(BookingLocation);
this.bookingRepo.insertBooking(Booking, BookingLocation); 

Раньше я не делал таких отношений, поэтому может быть далеко ...

Любая помощь приветствуется:)

Редактировать:

У меня теперь есть ошибка:

"Ссылка на объект не установлена ​​на экземпляробъект. "

... когда SessionFactory.OpenSession работает.

Это как-то связано с:

public class BookingLocation
{
        public BookingLocation(Booking inBooking)
        {
            this.Booking = inBooking;
            inBooking.AddBookingLocation(this);
        } 
}

... потому что когда я удаляюэто конструктор, который он запускает (думал без добавления BookingLocation)

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

Ответы [ 4 ]

2 голосов
/ 28 марта 2012

Я думаю, что это не ошибка NHibernate, а SqlServer, в частности схема таблицы.

Насколько я понимаю, вы не устанавливаете значения PK на клиенте и ожидаете, что идентификатор будет сгенерирован в базе данных, верно?

Ошибка, которую вы получаете от SqlServer, указывает, что таблица настроена для этого, но вы отправляете идентификатор в базу данных.

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

http://sqlserverplanet.com/sql-server/cannot-insert-explicit-value-for-identity-column-in-table-table-when-identity_insert-is-set-to-off

Но, возможно, это не то, что вы хотите сделать.

В этом примере возникает проблема при вставке в таблицу со столбцом Identity, когда вставка указывает идентификатор, который должен быть вставлен, а не позволяет таблице сгенерировать его. Т.е. table1 начинает увеличивать значения с 1, в то время как table2 начинается с 4. В этом примере запись успешно вставляется в table1 (эта строка будет иметь ID: 1), затем пытается вставить эту же строку, ID и все, в table2. Обычно при вставке в таблицу со столбцом Identity идентификатор не указывается, так как таблица сгенерирует его для вас.

Возможно, попробуйте установить значение DefaultValue в отображении на 0 в дополнение к GeneratedBy, предложенному Антоном. Это может помешать NHibernate отправлять значение столбца ID, равное 0. Это предполагает, что вы не пытаетесь генерировать идентификаторы в приложении, которые должны быть непосредственно вставлены в БД.


ответ на комментарий:

Если классу Booking требуется набор BookingLocations, таблице BookingLocation нужен FK, такой как BookingID. (иначе, ВЫБРАТЬ * из BookingLocation, ГДЕ BookingID = 123, возвращает вам список BookingLocations для бронирования 123)

Чтобы отобразить эту взаимосвязь, ваша карта бронирования должна выглядеть следующим образом (просто отображается сопоставление коллекции)

HasMany(x => x.BookingLocations)
   .KeyColumn("BookingID") // aka, column in BookingLocation that links a row to this Booking
   .Not.LazyLoad()
   //.Cascade.All() // would advise against this until you can get it working explicitly
   .Inverse() // use this instead
   ;

попробуйте изменить свое отображение ссылок следующим образом:

References(x => x.Booking)             
   .Column("BookingID") // the column in the locations table that points to the booking.
   .Not.LazyLoad()
   ;

Пометка этой коллекции как Cascade. Все означает, что вы не должны вручную сохранять (сессия. Сохранять) расположение резервирования.

И это также означает, что если вы когда-либо сохраняете Booking, вам необходимо убедиться, что вы загрузили BookingLocations, потому что я думаю, что без их загрузки ваша таблица BookingLocation будет выглядеть как коллекция внутри Booking. В этом случае, поскольку он пуст, он удалит BookingLocations. Точно так же вы, вероятно, захотите удалить Cascade.All из сопоставления ссылок бронирования в BookingLocation Т.е., если вы удаляете одно BookingLocation, вы не хотите удалять бронирование, связанное с ним - могут быть другие BookingLocations.

Как правило, я не использую Cascade в своих отображениях, а вместо этого устанавливаю свои коллекции как Inverse () . Однако при использовании обратного сопоставления коллекции BookingLocations не будет автоматически сохраняться при сохранении бронирования. Вам придется вернуться к их сохранению вручную:

using (var session = CreateNewSession())
{
    using (var trans = session.BeginTransaction())
    {
        session.Save(myNewBooking)
        myNewBooking.BookingLocations.ForEach(x => session.Save(x));
        trans.Commit();
    }
}

В итоге:


  Bookings (table)
  ID

  Booking_Locations (table)
  ID
  BookingID


  Booking (class)
  ID
  IList<BookingLocation>

  BookingLocation (class)
  ID
  Booking (instance)

BookingMap

base.HasMany<BookingLocation>(x => x.BookingLocations)
.KeyColumn("BookingID")
.Inverse()
.Not.LazyLoad()
;

BookingLocationMap

base.References<Booking>(x => x.Booking)
.Column("BookingID")
.Not.Nullable()
;

сохранение

var newBooking = new Booking(); // new booking
var newBLocation = new BookingLocation(); // new booking location
newBLocation.Booking = newBooking; // set booking instance on booking location
newBooking.BookingLocations.Add(newBLocation); // add new booking location to booking

session.Save(newBooking); // get the newBooking's ID from the DB insert
session.Save(newBLocation); // save the new location. NHibernate will set the FK col BookingID to the ID of the newly-persisted newBooking, and also get the new ID for newBLocation
1 голос
/ 28 марта 2012
public BookingLocationMap()
{
    Table("Bookings_Locations");    

    Id(x => x.Id).Column("ID").GeneratedBy.Identity(); // Try this


    References(x => x.Booking)             
      .Column("ID")             
      .Not.LazyLoad().Nullable()
      .Cascade.All();
}
0 голосов
/ 11 декабря 2014

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

В моем случае nhibernate также жаловался на попытку вставить значения в столбец идентификаторов.- даже если идентификатор никогда не устанавливался и, следовательно, приводил к «0» из-за его типа данных (long).

Решение было довольно простым ... Я забыл обернуть SaveOrUpdate в транзакцию: - / Я делал это много раз, но думаю, что это происходит во время ночных сессий argh

Надеюсь, что это кому-нибудь поможет.

Приветствия ...

0 голосов
/ 28 марта 2012

Почему бы не сделать свойство Id типа nullable int?Технически, вы не знаете значение сразу.

...