NHibernate与字符串主键和关系

时间:2009-01-04 22:41:26

标签: .net nhibernate nhibernate-mapping

我刚刚被这个问题困住了一个小时,我最终烦恼地发现了这个问题。

环境

我有一个用户将字符串作为主键的表,这个表具有多个一对多和多对多的关系。

当从表中搜索多个项目时,所有关系都被带回。但是每当我试图通过主键(字符串)获取对象时,它都没有带回任何关系,它们总是设置为0.

部分解决方案

所以我查看了我的日志,看看SQL正在做什么,并且返回了正确的结果。所以我以各种随机的方式尝试了各种各样的东西,最终得出结论。传递给get方法的字符串的情况与数据库中的情况完全不同,所以当它试图将关系项与主实体匹配时,它没有找到任何(或者至少是NHIbernate不是因为我上面说过SQL实际上正在返回正确的结果)

真正的解决方案

还有其他人遇到过这个吗?如果是这样,在将SQL结果与实体匹配时,如何告诉NHibernate忽略大小写?这很愚蠢,因为它在此之前运作得非常好,突然间它开始关注字符串的情况。

5 个答案:

答案 0 :(得分:4)

我的数据库中的ref表上的情况完全相同。我以与您相同的方式映射模式文件。在代码中,当我通过Primary Key查询记录时,我使用NHibernate ISession的实例执行以下操作:

return session.Get<T>(id);

在此声明中,T是您要查询的类型,id是您要查找的字符串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 :(得分:1)

为了保持一致,请修改一下:

<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映射的一部分?

将您的业务实体移到他们自己的库中,以便程序集名称始终相同。

答案 2 :(得分:1)

这是我的解决方法(这是一种解决方法;我正在处理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的一种不错的方法。

答案 3 :(得分:0)

没有选择,但您可以使用QBE

实现相同目的
Example.create(parent).ignoreCase() 

答案 4 :(得分:0)

我不明白你的问题:

  • 当您使用Get方法查询PK时,返回的对象没有关系值
  • 当您通过其他类型的查询查询时(示例会有用),关系不是空的?