Модель БД:
- 1 стол "Программное обеспечение"
- Столбец "ID" (длинный) -> Первичный ключ с автоматическим приращением
- Столбец «Совместимость» (длинный) -> НЕ ПУСТО, FK в «ИД»
- колонка "Описание" (варчар)
CREATE TABLE `softwares` (
`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
`CompatibilityID` BIGINT(20) NOT NULL,
`Description` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`ID`),
INDEX `FK_Software_Compatibility` (`CompatibilityID`),
CONSTRAINT `FK_Software_Compatibility` FOREIGN KEY (`CompatibilityID`) REFERENCES `softwares` (`ID`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=0
Эта таблица пуста.
При включенных проверках ссылок новая строка не может быть вставлена, поскольку проверка ссылок для столбца "Совместимость" требует допустимого значения в столбце "ID".
Но значение «ID» будет известно только после того, как была произведена вставка!
Единственный способ найти новую строку - временно отключить проверку ссылок в собственном SQL.
Вставка-Пример:
START TRANSACTION;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
INSERT
INTO
softwares
(Description)
VALUES
('MySoftware');
UPDATE `softwares`
SET
`CompatibilityID`=LAST_INSERT_ID()
WHERE `ID`=LAST_INSERT_ID();
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
COMMIT;
В нативном SQL это возможно, но я хочу сделать то же самое с NHibernate.
//class model
class Software
{
public virtual long ID { get; set; }
public virtual Software Compatibility { get; set; }
public virtual string Description { get; set; }
}
//mapping with FluentNHibernate
class SoftwareMap : ClassMap
{
public SoftwareMap()
{
Id(x => x.ID)
.GeneratedBy.Native();
References(x => x.Compatibility)
.Column("CompatibilityID")
.ForeignKey("FK_Software_Compatibility")
.Not.Nullable();
Map(x => x.Description);
}
}
Код для вставки программных записей:
Software software1 = new Software();
software1.Description = "Test software 1";
software1.Compatibility = software1;
Software software2 = new Software();
software2.Description = "Test software 2";
software2.Compatibility = software1;
using (ITransaction transaction = Session.BeginTransaction()) {
//ISQLQuery queryChecksOff = Session.CreateSQLQuery("/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;");
//int dummy = queryChecksOff.ExecuteUpdate();
Session.Save(software1);
Session.Save(software2);
//ISQLQuery queryChecksOn = Session.CreateSQLQuery("/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;");
//dummy = queryChecksOn.ExecuteUpdate();
transaction.Commit();
}
NHibernate выдает ошибку при выполнении строки "Session.Save (software1);":
«свойство not-null ссылается на нулевое или временное значение Domain.Software.Compatibility»
Эта ошибка является правильной, поскольку указанное программное обеспечение «software1» еще не было сохранено в БД!
Я пытался отключить проверки целостности перед вставкой с помощью «CreateSQLQuery ()» в приведенном выше коде, но безуспешно.
Это также имеет смысл, поскольку NHibernate не отправлял SQL-операторы в БД из-за неправильной целостности.
Теперь, что я могу сделать?
1) Могу ли я отключить проверку целостности NHibernate? (Было бы плохое кодирование ...)
2) Могу ли я сказать NHibernate, что эта ссылка в порядке или обрабатывается по-другому?
3) Модель БД неверна?