2009-01-04 8 views
5

Je viens d'être perplexe avec ce problème pendant une heure et j'ai finalement trouvé le problème ennuyeux.NHibernate avec la clé primaire et les relations

LES CIRCONSTANCES

J'ai une table que les utilisateurs d'une chaîne comme une clé primaire, ce tableau a plusieurs plusieurs à un et plusieurs à plusieurs relations tout au large de cette clé primaire.

Lors de la recherche de plusieurs éléments de la table, toutes les relations ont été rétablies. Cependant chaque fois que j'ai essayé d'obtenir l'objet par la clé primaire (chaîne), il n'a pas été ramène les relations, ils étaient toujours à 0.

LA SOLUTION PARTIELLE

Je me regarda dans les journaux à voir ce que le SQL faisait et qui renvoyait les bons résultats. J'ai donc essayé différentes choses de toutes sortes de manières aléatoires et finalement j'ai travaillé. Le cas de la chaîne passée dans la méthode get n'était pas EXACTEMENT le même que dans la base de données, donc quand elle essayait de faire correspondre les éléments de relation avec l'entité principale, elle ne trouvait rien (ou au moins NHIbernate wasn ' t parce que je l'ai dit au-dessus du SQL a été fait renvoyer les résultats corrects)

lA SOLUTION REAL

quelqu'un at-il rencontré ce? Si oui, comment dites-vous à NHibernate d'ignorer le cas lors de la correspondance des résultats SQL à l'entité? C'est bête parce que ça fonctionnait parfaitement bien maintenant tout d'un coup il a commencé à faire attention au cas de la ficelle.

+0

Pouvez-vous envoyer vos fichiers de cartographie? – Craig

+0

Le boîtier est-il correct pour les articles nouvellement ajoutés? Avez-vous mis à jour NHibernate dernièrement? SQL est généralement sensible à la casse, mais en utilisant les instructions "LIKE", elles peuvent être toutes deux dépendantes du dialecte, mais vous ne voulez pas l'utiliser pour résoudre les relations. – jishi

Répondre

4

J'ai exactement la même situation sur une table de référence dans ma base de données. J'ai mappé le fichier de schéma de la même manière que vous l'avez fait. Dans le code, quand je fais une recherche de l'enregistrement par clé primaire, je fais ce qui suit en utilisant une instance de la NHibernate ISession:

return session.Get<T>(id); 

Dans cette déclaration, T est le type que vous interrogez pour, et id est la chaîne id que vous recherchez (la clé primaire)

Voici un exemple de mon fichier de mapping:

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

Et mon code C# ressemble à ceci:

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

Il n'y a pas d'option pour cela, mais vous pouvez obtenir le même en utilisant QBE

Example.create(parent).ignoreCase() 
0

Je ne comprends pas votre problème:

  • lorsque vous interrogez le PK avec méthode Get, l'objet retourné n'a aucune valeur pour les relations
  • lorsque vous interrogez par un autre type de requête (un exemple sera utile), les relations ne sont pas vides?
1

Par souci de cohérence, s'il vous plaît réviser ceci:

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

Plus précisément "App_Code.tqeub3fb". Il semble que vous utilisiez des assemblys temporaires à partir d'un site Web ASP.NET dans le cadre du mappage de NHibernate?

Déplacez vos entités commerciales dans leur propre bibliothèque afin que le nom de l'assemblage soit toujours le même.

1

Voici ma solution de contournement (et c'est une solution de contournement, j'ai affaire à un DB in-situ qui a été mal conçu IMO).

origine Provenant: https://forum.hibernate.org/viewtopic.php?f=25&t=979685&view=previous

Voici ma classe de chaîne personnalisée (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 

Et j'utiliser FluentNhibernate, voici donc ce que le mapping ressemble à (appliquer uniquement aux champs Id):

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

Et c'était ça; mes associations ont commencé à être correctement peuplées à nouveau. Encore une fois, il est BEAUCOUP meilleur de concevoir correctement votre base de données en utilisant des PK int/GUID plutôt que des chaînes, mais si vous devez le faire, c'est une façon correcte de "réparer" NHibernate.

+0

Ajoutez .Trim() à x et y dans String.Equals si vous pensez que vous pourriez avoir à vous en soucier. – kamranicus

Questions connexes