2010-07-05 10 views
1

Je le mappage suivant:Pourquoi NHibernate effectue-t-il un INSERT au lieu d'une mise à jour?

<!-- WidgetConfiguration --> 
<class name="MyProject.WidgetConfiguration, MyProject" table="WidgetConfigurations"> 
    <id name="Id" column="Id" type="Int64"> 
    <generator class="native" /> 
    </id> 

    <property name="Name" column="ConfigurationName" /> 

    <map name="Widgets" table="WidgetConfigurationPositions" cascade="all" lazy="false" fetch="select" inverse="true"> 
    <key column="WidgetConfigurationId" /> 
    <index column="TargetId" type="string" /> 
    <one-to-many class="MyProject.WidgetPlacement" /> 
    </map> 
</class> 
<!-- End WidgetConfiguration --> 

<class name="MyProject.WidgetPlacement, MyProject" table="WidgetConfigurationPositions"> 
    <id name="Id" column="Id" type="Int64"> 
    <generator class="native" /> 
    </id> 

    <many-to-one name="Widget" class="MyProject.Widget, MyProject" column="WidgetId" lazy="false" /> 
    <property name="Target" column="TargetId" not-null="true" /> 

    <map name="Options" table="PlacedWidgetOptions" cascade="all" lazy="false" fetch="select"> 
    <key column="WidgetConfigurationPositionId"/> 
    <index column="OptionName" type="string" /> 
    <element column="OptionValue" type="string" /> 
    </map> 
</class> 

Et, je le bit de code suivant:

public override void Update(WidgetConfiguration obj) 
{ 
using (var session = GetSession()) 
{ 
    var tx = session.BeginTransaction(); 
    session.Update(obj); 
    tx.Commit(); 

    //session.Evict(obj); 
} 
} 

je peux sauver un WidgetConfiguration dandy, mais en essayant mettre à jour un WidgetConfiguration, NHibernate effectue effectivement un insert! Voici la session de mon profileur NHibernate.

begin transaction with isolation level: Unspecified 

INSERT INTO WidgetConfigurations 
      (ConfigurationName) 
VALUES  ('dashboard' /* @p0 */) 
select SCOPE_IDENTITY() 

INSERT INTO WidgetConfigurationPositions 
      (WidgetId, 
      TargetId) 
VALUES  (1 /* @p0 */, 
      'row1-column1' /* @p1 */) 
select SCOPE_IDENTITY() 

UPDATE WidgetConfigurationPositions 
SET WidgetId = 1 /* @p0 */, 
     TargetId = 'row1-column2' /* @p1 */ 
WHERE Id = 356 /* @p2 */ 

commit transaction 

J'ai pas idée pourquoi cela se passe et Google ne pas être très utile. Quelqu'un a des idées?

+0

Comment obtenez-vous cette instance WidgetConfiguration? Vous l'extrayez de la base de données via session.Get(), session.Load() ou une autre requête? –

+0

Maurico, je l'obtiens via une requête. var query = session.CreateQuery ("FROM WidgetConfigurations wc INNER JOIN FETCH ..."); return query.UniqueResult () ;. Comment devrais-je le faire? –

+0

Ça va, je vérifiais, juste au cas où ... –

Répondre

0

Mon suppose que votre problème est provoqué en récupérant l'objet dans une session NH et en le mettant à jour dans un autre. Gardez la session NH ouverte pendant toute la durée de la requête, ou essayez d'attacher (Lock()?) L'objet à la session NH de mise à jour.

+0

Comment nh détermine-t-il quelle opération effectuer, par exemple, SaveOrUpdate? J'ai toujours supposé que si le champ ID était défini, il serait mis à jour. –

+0

Je le pensais aussi mais c'est une utilisation supportée: http://knol.google.com/k/fabio-maulo/nhibernate-chapter-9-manipulating/1nr4enxv3dpeq/12#9%282E%294%282E%29% 28C2% 29% 28A0% 29Updating_objects –

3

Essayez définissant l'attribut unsaved-value:

<id name="Id" column="Id" type="Int64" unsaved-value="0"> 
    <generator class="native" /> 
</id> 

Quel est le type de la colonne ID? Si c'est long? alors la valeur non sauvegardée doit être null. Vous ne devriez pas avoir besoin de mettre cela mais c'est la première chose que j'essaierais.

2

Rappelez-vous de surcharger vos Equals() et GetHashCode()? Puisque vous vous détachez et que vous réattachez ces méthodes, elles entreront en jeu.

Je recommande ramasser NHibernate dans l'action et la lecture sur le cycle de vie de la persistance :)

Questions connexes