Съставен ключ на картографиране с колона без картографиране

Как да картографирам съставен ключ, ако част от него не е картографиран в моя обект?

Пример:

Имам таблица ITEMDELIVERY, съдържаща колоните:

  • ITEMDELIVERY_ID (PK)
  • DELIVERY_DATE (PK)

Имам таблица ITEMDELIVERYDETAIL, съдържаща колоните:

  • ITEMDELIVERYDETAIL_ID (PK)
  • ITEMDELIVERY_ID (FK)
  • PARTITIONDATE (PK, FK)

Както можете да видите, има съставен ключ и в двете таблици, а ITEMDELIVERYDETAIL има "съставен" външен ключ към ITEMDELIVERY.

В моя модел на домейн ItemDeliveryDetail не съществува свойство PartitionDate, което да може да бъде съпоставено с колона PARTITIONDATE (вижте тук и тук за причините).

Но сега, как да картографирам съставния ключ в ITEMDELIVERYDETAIL?

Опитах следното, но не работи:

mapping.CompositeId().KeyProperty(x => x.Id, "ITEMDELIVERYDETAIL_ID")
                     .KeyProperty(x => x.ItemDelivery.DeliveryDate,
                                       "PARTITIONDATE");

Получавам следната грешка:

NHibernate.PropertyNotFoundException: Не може да се намери инструмент за получаване на свойството „DeliveryDate“ в клас „REM.Domain.NHibernate.ItemDeliveryDetail“


АКТУАЛИЗАЦИЯ:

Мисля, че намерих решението:

  1. Премахнете препратката към ItemDelivery от картографирането на ItemDeliveryDetail: mapping.References(x => x.ItemDelivery);.Columns("ITEMDELIVERY_ID", "PARTITIONDATE");
  2. Променете декларацията на съставния ключ на това:

    mapping.CompositeId().KeyProperty(x => x.Id, "ITEMDELIVERYDETAIL_ID")
                         .KeyReference(x => x.ItemDelivery, "ITEMDELIVERY_ID",
                                                            "PARTITIONDATE");
    

Това има страничен ефект, че записването на ItemDeliveryDetail не може да каскадно записва ItemDelivery. Трябва да се запази предварително.

Чудя се обаче едно нещо:
Това ще създаде ли ПК с три колони? Ако е така, как да го избегнете и да създадете PK само за двете необходими колони?


person Daniel Hilgarth    schedule 13.12.2011    source източник


Отговори (1)


изглежда, че имате наследена база данни и никога няма да я генерирате със SchemaExport, така че няма значение дали NH смята, че има 3 PK колони или 1.

след като разгледате вашия въпрос Композитен ключ с последователност и ако вашият идентификатор е уникален сам, тогава би било по-добре да

mapping.Id(x => x.Id).GeneratedBy.SequenceIdentity("SQ_TRANSFORM_ITEMDEL_IDDID");
mapping.Reference(x => x.ItemDelivery).Columns("ITEMDELIVERY_ID", "PARTITIONDATE");

дори ако в db PK обхваща и двете колони

Актуализация: сложно нещо във вашия пример за фактура. Има хак да има втората колона в съединението (като място, което оптимизаторът на заявките трябва да добави към съединението)

HasManyToMany(u => u.ItemDeliveryDetails)
    .Table("INVOICEITEM_IDD")
    .ChildWhere("PARTITIONDATE = nhGeneratedAliasForINVOICEITEM_IDD.PARTITIONDATE");
person Firo    schedule 14.12.2011
comment
Вашето предположение за наследената база данни е правилно. Въпреки това тестовата база данни, която ще се използва за тестове за спецификация на устойчивост, трябва да бъде създадена чрез експортиране на схема, за да се осигури чиста и надеждна тестова среда. - person Daniel Hilgarth; 14.12.2011
comment
имам същия сценарий, наследена база данни и модулни тестове за съпоставянията. Аз обаче не използвам SchemaExport, защото може да маскира грешки при картографиране. Експортирах схемата на производствената база данни в sqlscript, който изпълнявам веднага след създаването на sessionfactory. - person Firo; 14.12.2011
comment
Добра точка. Все пак има друга причина, поради която трябва да имам правилните съпоставяния: има таблици, които имат външен ключ към ITEMDELIVERYDETAIL. За да се гарантира, че генерираните съединения са възможно най-бързи, този външен ключ също трябва да използва и двете колони. Ако използвам вашия отговор, това няма да работи, защото ITEMDELIVERYDETAIL е картографиран само с един идентификатор... - person Daniel Hilgarth; 14.12.2011
comment
Сигурни ли сте, че производителността се влошава толкова много в Oracle, ако се присъедини само една колона от индекса (pk)? Не мога да измисля начин да симулирам db схемата в съпоставянията без много проблеми - person Firo; 14.12.2011
comment
да Това беше цялата цел на въвеждането на тази колона и дяловете, когато създадохме тази база данни. Това е доста голяма таблица с 30 милиона записа... Само няколко числа: Присъединяването без датата на разделяне за един ред отнема 11 секунди. Присъединяването с датата на разделяне е мигновено. - person Daniel Hilgarth; 14.12.2011
comment
Можете ли да публикувате другия обект, който препраща към ItemDeliveryDetail? Може би мога да намеря просто решение за това. В противен случай ще стане неприятна/трудна работа, опитвайки се да го картографирате като в db. - person Firo; 14.12.2011
comment
Един пример би бил проста таблица за съпоставяне INVOICEITEM_IDD с колони INVOICEITEM_ID, ITEMDELIVERYDETAIL_ID и PARTITIONDATE, като последните две колони са FK към ITEMDELIVERYDETAIL По този начин ще имам HasManyToMany relationshop в моя InvoiceItem обект и тази връзка ще трябва да използва двете колони . - person Daniel Hilgarth; 14.12.2011
comment
Току-що се опитах отново да разреша този проблем и разбрах, че сте актуализирали отговора си през декември. Съжалявам, пропуснал съм го! Има ли подобен хак, ако просто препращам към таблицата (както в mapping.References)? Може би с Formula? - person Daniel Hilgarth; 27.01.2012