2009-01-04 14 views
5

He estado perplejo con este problema durante una hora y encontré el problema con el tiempo.NHibernate con clave principal de cadena y relaciones

LAS CIRCUNSTANCIAS

que tienen una tabla que los usuarios de una cadena como una clave principal, esta tabla tiene varios a muchos a uno y muchos a muchas relaciones ALL OFF esta clave primaria.

Al buscar varios elementos de la tabla, se restablecieron todas las relaciones. Sin embargo cada vez que trataba de conseguir el objeto de la clave principal (cadena) no fue trayendo de nuevo cualquier relación, siempre que se ponen a 0.

LA SOLUCIÓN PARCIAL

Así que miró a los registros de ver lo que estaba haciendo el SQL y que estaba devolviendo los resultados correctos. Así que probé varias cosas en todo tipo de formas al azar y finalmente funcionó. El caso de la cadena que se pasó al método get no fue EXACTAMENTE el mismo caso que en la base de datos, por lo que cuando intentó hacer coincidir los elementos de la relación con la entidad principal no encontró nada (O al menos NHIbernate wasn ' t porque como he dicho anteriormente el SQL se vuelve realidad los resultados correctos)

la solución real

alguien más ha encontrado esto? Si es así, ¿cómo le dices a NHibernate que ignore el caso al hacer coincidir los resultados de SQL con la entidad? Es una tontería porque funcionó perfectamente bien ahora, de repente, ha comenzado a prestar atención al caso de la cuerda.

+0

¿Puedes publicar tus archivos de mapeo? – Craig

+0

¿Es la carcasa correcta para los artículos recién agregados? ¿Has actualizado NHibernate últimamente? SQL generalmente distingue entre mayúsculas y minúsculas, sin embargo, al usar las afirmaciones "LIKE" pueden ser ambas dependientes del dialecto, pero no desea utilizarlas al resolver las relaciones. – jishi

Respuesta

4

Tengo exactamente la misma situación en una tabla de referencia en mi base de datos. Mapeé el archivo de esquema de la misma manera que lo hizo. En el código, cuando consulta para el disco de clave principal, hago lo siguiente utilizando una instancia del NHibernate ISession:

return session.Get<T>(id); 

En esta declaración, T es el tipo que está consultando para, y la identificación es la cadena Identificación del que está buscando (la clave principal)

Aquí es un ejemplo de mi archivo de asignación:

<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> 

Y mi C# código es el siguiente:

public Merchant GetMerchantById(string id) 
{ 
    return session.Get<Merchant>(id); 
} 
0

No hay ninguna opción para esto, pero se puede lograr el mismo usando QBE

Example.create(parent).ignoreCase() 
0

No entiendo su problema:

  • cuando se consulta por el PK con método GET, el objeto devuelto no tiene ningún valor para las relaciones
  • cuando consulta por otro tipo de consulta (un ejemplo será útil), las relaciones no están vacías?
1

Por razones de consistencia, por favor revisar esta:

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

Más específicamente "App_Code.tqeub3fb". Parece que está utilizando ensambles temporales de un sitio web ASP.NET como parte del mapeo de NHibernate.

Mueva sus Entidades comerciales a su propia biblioteca para que el nombre del ensamblado sea siempre el mismo.

1

Aquí está mi solución (y es una solución, estoy tratando con un DB en el lugar que fue diseñado mal IMO).

procedentes originalmente de: https://forum.hibernate.org/viewtopic.php?f=25&t=979685&view=previous

Aquí es mi clase de cadena personalizada (en 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 

Y uso FluentNhibernate, así que aquí es lo que el mapeo se parece (sólo se aplica a los campos de ID):

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

Y eso fue todo; mis asociaciones comenzaron a poblarse adecuadamente nuevamente.

Una vez más, es MUCHO mejor diseñar su base de datos utilizando int/GUID PK en lugar de cadenas, pero si es necesario, esta es una forma decente de "arreglar" NHibernate.

+0

Agregue .Trim() a xey en los String.Equals si cree que puede necesitar preocuparse por eso. – kamranicus

Cuestiones relacionadas