NHibernate со строковым первичным ключом и отношениями - PullRequest
5 голосов
/ 05 января 2009

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

ОБСТОЯТЕЛЬСТВА

У меня есть таблица, в которой в качестве первичного ключа используется строка, эта таблица имеет различные отношения «многие к одному» и «многие ко многим», все эти первичные ключи.

При поиске нескольких элементов из таблицы все отношения возвращались. Однако всякий раз, когда я пытался получить объект по первичному ключу (строке), он не возвращал никаких отношений, они всегда были равны 0.

ЧАСТИЧНОЕ РЕШЕНИЕ

Поэтому я заглянул в свои журналы, чтобы увидеть, что делает SQL, и это возвращает правильные результаты. Так что я пробовал разные вещи разными способами, и в итоге все получилось. Случай передачи строки в метод get не был точно таким же, как в базе данных, поэтому, когда он пытался сопоставить элементы отношений с основным объектом, он ничего не находил (или, по крайней мере, NHIbernate не потому, что, как я уже говорил выше, SQL на самом деле возвращал правильные результаты)

РЕАЛЬНОЕ РЕШЕНИЕ

Кто-нибудь еще сталкивался с этим? Если так, как вы говорите NHibernate игнорировать регистр при сопоставлении результатов SQL с сущностью? Это глупо, потому что это сработало на отлично, но теперь внезапно стало обращать внимание на случай строки.

Ответы [ 5 ]

4 голосов
/ 15 января 2009

У меня точно такая же ситуация с таблицей ссылок в моей БД. Я отобразил файл схемы так же, как вы. В коде, когда я запрашиваю запись по первичному ключу, я делаю следующее с использованием экземпляра NHibernate ISession:

return session.Get<T>(id);

В этом выражении T - это тип, который вы запрашиваете, а id - это идентификатор строки, которую вы ищете (первичный ключ)

Вот пример моего файла сопоставления:

    <class name="Merchant" table="T__MERCHANT">
        <id name="MerchantId" column="MERCHANT_ID" type="string">
            <generator class="assigned" />
        </id>

        <property name="MerchantStatusId" column="MERCHANT_STATUS_ID" type="Char" not-null="true" length="1" />
        <property name="MerchantStatusName" column="MERCHANT_STATUS_NAME" type="string" length="50" />
        <property name="MerchantName" column="NAME" type="string" not-null="true" length="50" />
 </class>
</hibernate-mapping>

И мой код C # выглядит так:

public Merchant GetMerchantById(string id)
{
     return session.Get<Merchant>(id);
}
1 голос
/ 05 января 2011

Вот мой обходной путь (и это обходной путь; я имею дело с базой данных на месте, которая была разработана плохо IMO).

Источник: https://forum.hibernate.org/viewtopic.php?f=25&t=979685&view=previous

Вот мой класс пользовательских строк (в VB):

Imports NHibernate.UserTypes
Imports NHibernate.Type
Imports NHibernate.SqlTypes

Public Class CaseInsensitiveStringType
    Inherits AbstractStringType

    ' Methods
    Public Sub New()
        MyBase.New(New StringSqlType)
    End Sub

    Public Sub New(ByVal sqlType As StringSqlType)
        MyBase.New(sqlType)
    End Sub


    ' Properties
    Public Overrides ReadOnly Property Name As String
        Get
            Return "InsensitiveString"
        End Get
    End Property

    Public Overrides Function IsEqual(ByVal x As Object, ByVal y As Object) As Boolean
        Return MyBase.IsEqual(x, y) OrElse (x IsNot Nothing AndAlso y IsNot Nothing AndAlso String.Equals(x, y, StringComparison.InvariantCultureIgnoreCase))
    End Function

    Public Overrides Function GetHashCode(ByVal x As Object, ByVal entityMode As NHibernate.EntityMode, ByVal factory As NHibernate.Engine.ISessionFactoryImplementor) As Integer
        Return MyBase.GetHashCode(x.ToString().Trim().ToUpperInvariant(), entityMode, factory)
    End Function
End Class

И я использую FluentNhibernate, поэтому вот как выглядит отображение (применимо только к полям Id):

Id(Function(x) x.Id).GeneratedBy.Assigned().CustomType(Of CaseInsensitiveStringType)()

И это было то; мои ассоциации снова начали правильно заполняться.

Опять же, НАМНОГО лучше правильно спроектировать вашу БД, используя int / GUID PK, а не строки, но если вам нужно, это достойный способ "исправить" NHibernate.

1 голос
/ 24 февраля 2009

Для согласованности, пожалуйста, измените это:

<joined-subclass name="JohnHarmanLtd.Web.FineArtCompany.Models.Book, App_Code.tqeub3fb, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">

Более конкретно: " App_Code.tqeub3fb ". Похоже, вы используете временные сборки с веб-сайта ASP.NET как часть сопоставления для NHibernate?

Переместите свои бизнес-объекты в их собственную библиотеку, чтобы имя сборки всегда было одинаковым.

0 голосов
/ 23 февраля 2009

Я не понимаю вашу проблему:

  • когда вы запрашиваете у PK метод Get, возвращаемый объект не имеет значения для отношений
  • когда вы запрашиваете запрос другого типа (пример будет полезен), отношения не пусты?
0 голосов
/ 09 февраля 2009

Нет возможности для этого, но вы можете добиться того же, используя QBE

Example.create(parent).ignoreCase() 
...