Question

Je dois mapper deux tables simples avec une relation de clé étrangère. L’un des tableaux est Contact contenant les colonnes id (clé primaire de type int), nom , adresse et < strong> guid (nouvellement ajouté et n'est pas la clé primaire). L’autre est phone__number contenant les colonnes id (clé primaire de type int), contact ___ id (clé étrangère de l’id dans la table des contacts) et numéro de téléphone .

Le fichier de mappage de la table Contact est le suivant:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="OfflineDbSyncWithNHibernate" default-lazy="true" namespace="OfflineDbSyncWithNHibernate.Models">
  <class name="Contact" table="Contact">
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>

    <property name="Name" column="name" type="string"/>
    <property name="Address" column="address" type="string"/>
    <property name="Guid" column="guid" type="string"/>

    <set lazy="true" batch-size="6" table="phone_number" name="PhoneNumbers" fetch="join" inverse="false" cascade="all" >
      <key foreign-key="FK_contact_phone_number" column="contact_id"/>
      <one-to-many class="PhoneNumber" />
    </set>

  </class>
</hibernate-mapping>

Le fichier de mappage pour la table Phone_number est:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="OfflineDbSyncWithNHibernate" default-lazy="true" namespace="OfflineDbSyncWithNHibernate.Models">
  <class name="PhoneNumber" table="phone_number">
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="ContactId" column="contact_id" />
    <property name="Number" column="phone_number" />
  </class>
</hibernate-mapping>

Les classes Contact et PhoneNumber sont les suivantes:

namespace OfflineDbSyncWithNHibernate.Models
{
    public class Contact
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string Address { get; set; }
        public virtual string Guid { get; set; }
        public virtual PhoneNumbers PhoneNumbers { get; set; }
    }
}

namespace OfflineDbSyncWithNHibernate.Models
{
    public class PhoneNumber
    {
        public virtual int Id { get; set; }
        public virtual int ContactId { get; set; }
        public virtual string Number { get; set; }
    }
}

namespace OfflineDbSyncWithNHibernate.Models
{
    public class PhoneNumbers : List<PhoneNumber>
    {
    }
}

Lorsque je charge le contact et les numéros de téléphone séparément, cela fonctionne, mais après l'ajout de l'élément set pour obtenir une relation un à plusieurs, nhibernate génère une erreur:

NHibernate.MappingException: informations de mappage non valides spécifiées pour le type OfflineDbSyncWithNHibernate.Models.Contact, vérifiez dans votre fichier de mappage les incompatibilités de type de propriété

Je suis nouveau sur nHibernate, je ne suis donc pas sûr qu'il y ait une erreur dans l'élément set ou même que je ne devrais même pas l'utiliser. Toute aide sera appréciée.

Était-ce utile?

La solution

Rappelez-vous simplement ceci

  • Le sac est implémenté avec IList
  • L'ensemble est mis en oeuvre avec ISet
  • La liste est implémentée à l'aide de ArrayList ou List
  • La carte est implémentée avec HashedTable ou IDictionary

Si vous souhaitez utiliser IList, utilisez la première règle, c.-à-d. changez votre fichier hbm.xml pour utiliser Bag au lieu de Set, votre classe Phonenumbers doit hériter de IList not List, si vous souhaitez utiliser List, vous devrez modifier votre fichier de mappage en utilisez List au lieu de Set.

Autres conseils

Je pense que votre classe PhoneNumbers doit hériter d'un sous-type de Iesi.Collections.ISet. Je ne pense pas qu’il existe un & "Ensemble &"; type fourni par défaut dans .NET. Voir hibernate FAQ

  

Le < set > cartes à un   Iesi.Collections.ISet. Cette interface   fait partie de la Iesi.Collections   ensemble distribué avec NHibernate.

Votre type de collection doit être une interface, car NHibernate fournira son propre type qui implémentera cette interface lorsqu'un objet est extrait de la base de données.

Si vous définissez votre collection comme

public virtual ISet<PhoneNumber> Phonenumbers = new HashedSet<Phonenumber>();

Ensuite, je pense que cela fonctionnera.

Pour mieux contrôler l'accès à votre collection, vous pouvez modifier votre classe Contact comme suit:

public class Contact
{
    public virtual int Id {get;set;}
    ..

    private ISet<Phonenumber> _phoneNumbers = new HashedSet<PhoneNumber>();

    public ReadOnlyCollection<Phonenumber> PhoneNumbers
    {
        get 
        {
           return new List<Phonenumber>(_phoneNumbers).AsReadOnly();
        }
    }

    public void AddPhonenumber( Phonenumber n )  
    {
        n.Contact = this;
        _phoneNumbers.Add(n);
    }

    public void RemovePhoneNumber( PhoneNumber n )
    {
        ...
    }
}

Ensuite, vous devez vous assurer que, dans votre mappage de la classe Contact, vous indiquez que NHibernate doit accéder au champ _phoneNumbers au lieu de la propriété PhoneNumber:

<set name="PhoneNumbers" access="field.camelcase-underscore" ... >
   ...
</set>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top