Domanda

Devo mappare due semplici tabelle con una relazione di chiave esterna. Una delle tabelle è Contatto contenente le colonne ID (chiave primaria di tipo int), nome , indirizzo e < strong> guid (appena aggiunto e non è la chiave primaria). L'altro è phone__number contenente le colonne ID (chiave primaria di tipo int), contact___id (chiave esterna di id nella tabella dei contatti) e phone__number .

Il file di mapping per la tabella dei contatti è il seguente:

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

Il file di mapping per la tabella Phone_number è:

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

Le classi Contact e PhoneNumber sono:

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

Quando carico il contatto e i numeri di telefono separatamente funziona, ma dopo aver aggiunto l'elemento set per ottenere una relazione uno a molti, viene visualizzato un errore:

NHibernate.MappingException: informazioni di mappatura non valide specificate per il tipo OfflineDbSyncWithNHibernate.Models.Contact, controlla il file di mappatura per mancate corrispondenze del tipo di proprietà

Sono nuovo di nHibernate, quindi non sono sicuro che ci sia un errore nell'elemento set o non dovrei nemmeno usarlo. Qualsiasi aiuto sarà apprezzato.

È stato utile?

Soluzione

Ricorda questo

  • Bag è implementato utilizzando IList
  • Il set è implementato usando ISet
  • L'elenco viene implementato utilizzando ArrayList o Elenco
  • La mappa viene implementata utilizzando HashedTable o IDictionary

Se vuoi usare IList usa la prima regola, cioè cambia il tuo hbm.xml per usare Bag invece di Set anche la tua classe Phonenumbers dovrebbe ereditare da IList non List, se vuoi usare List dovrai cambiare il tuo file di mapping in usa Elenco invece di Set.

Altri suggerimenti

Penso che la tua classe PhoneNumbers debba ereditare da un sottotipo di Iesi.Collections.ISet. Non credo che ci sia un & Quot; Set & Quot; tipo fornito in .NET per impostazione predefinita. Vedi hibernate FAQ

  

< set > è mappato a un   Iesi.Collections.ISet. Quell'interfaccia   fa parte di Iesi.Collections   assemblea distribuita con NHibernate.

Il tipo di raccolta dovrebbe essere un'interfaccia, poiché NHibernate fornirà il proprio tipo che implementa tale interfaccia quando un oggetto viene recuperato dal DB.

Se definisci la tua raccolta come

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

Quindi penso che funzionerà.

Per controllare meglio l'accesso alla tua raccolta, puoi modificare la tua classe di contatto in questo modo:

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 )
    {
        ...
    }
}

Quindi, devi assicurarti che nel tuo mapping della classe Contact, specifichi che NHibernate dovrebbe accedere al campo _phoneNumbers invece della proprietà PhoneNumber:

<set name="PhoneNumbers" access="field.camelcase-underscore" ... >
   ...
</set>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top