Сопоставить составной ключ с несопоставленным столбцом

Как сопоставить составной ключ, если его часть не сопоставляется с моей сущностью?

Пример:

У меня есть таблица 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");

даже если в БД ПК охватывает оба столбца

Обновление: сложная вещь в вашем примере Invoice. Существует хак, чтобы иметь второй столбец в соединении (как место, которое оптимизатор запросов должен добавить в соединение)

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
Вы уверены, что производительность оракула так сильно снижается, если соединяется только один столбец индекса (pk)? Я не могу придумать способ имитировать схему БД в сопоставлениях без особых проблем. - 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 в моем объекте InvoiceItem, и это отношение должно будет использовать два столбца. . - person Daniel Hilgarth; 14.12.2011
comment
Я только сейчас снова попытался решить эту проблему и понял, что вы обновили свой ответ еще в декабре. Извините, я пропустил это! Есть ли аналогичный хак, если я просто ссылаюсь на таблицу (как в mapping.References)? Может с Formula? - person Daniel Hilgarth; 27.01.2012