2010-03-04 9 views
0

J'ai une simple table parent/enfant. Le contrat est la table parent. Chaque contrat peut avoir plusieurs unités.Exception de suppression des enregistrements enfants dans NHibernate

Voici mes définitions de classe C# (simplifié):

public class Contract : EntityWithIntID 
{ 
    public virtual string ContractNum { get; set; } 
    public virtual IList<Unit> Units { get; protected set; } 
    public virtual int NumberOfUnits 
    { 
     get { return Units.Count; } 
    } 
} 

    public class Unit : EntityWithIntID 
{ 
    <various Unit physical data fields> 
} 

J'utilise FluentNHibernate avec AutoMapping. Voici ma classe AutoMapping:

public static AutoPersistenceModel GetMappings() 
    { 
     AutoPersistenceModel returnModel = AutoMap.AssemblyOf<Contract>() 
      .IgnoreBase(typeof(EntityWithIntID)) 
      .Where(type => type.BaseType == typeof(EntityWithIntID)) 
      .Conventions.Add(typeof(PluralTableNamesConvention)) 
      .Conventions.Add(typeof(CascadeAllConvention)) 
      .Override<Contract>(map =>map.HasMany(cont =>cont.Units).Inverse()) 
      .Override<Contract>(map=>map.Map(cont => cont.ContractNum).Not.Nullable().Unique()) 
     ; 
     return returnModel; 
    } 
} 

Voici les fichiers hbm.xml que Fluent génère:

(pour la table unités):

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
<class xmlns="urn:nhibernate-mapping-2.2" name="InterfaceDB.Unit, InterfaceDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Units"> 
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Id" /> 
     <generator class="hilo"> 
     <param name="max_lo">10</param> 
     </generator> 
    </id> 
<!-- physical data property elements removed for brevity --> 
    </class> 
</hibernate-mapping> 

(et pour la table des contrats):

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="InterfaceDB.Contract, InterfaceDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Contracts"> 
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Id" /> 
     <generator class="hilo"> 
     <param name="max_lo">10</param> 
     </generator> 
    </id> 
    <property name="ContractNum" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="ContractNum" not-null="true" unique="true" /> 
    </property> 
    <bag cascade="all" inverse="true" name="Units"> 
     <key> 
     <column name="Contract_id" /> 
     </key> 
     <one-to-many class="InterfaceDB.Unit, InterfaceDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
    </class> 
</hibernate-mapping> 

Pour mes fins de tests unitaires, j'ai une méthode « Clear() » dans chacun des dépôts afin que je puisse commencer une base de données vide connue. Il fait tout simplement un

Session.Delete("from Unit"); 

suivi d'un (== Repository.GetCount() 0) Debug.Assert;

Mon problème est que quand je fais un UnitsRepository.Clear(), je reçois un NHibernate.ObjectDeleteException: objet supprimé sera à nouveau enregistré par cascade (supprimer objet supprimé des associations)

Je googled cette erreur , et a trouvé un certain nombre d'articles à ce sujet, mais rien n'a semblé fonctionner. J'ai ajouté le ".Inverse()" sur le mappage parent. J'ai essayé de changer la cascade de "All" à "SaveUpdate" (il n'a jamais été réglé sur "AllDeleteOrphans", ce que certains messages ont cité comme étant le problème.) Je nettoie tous les dépôts, et j'ai essayé de tout emballer dans un transaction. J'ai essayé d'ajouter un flush après la Session.Delete. J'ai d'abord effacé le référentiel parent, puis l'enfant. Rien ne se débarrasse de l'erreur.

Toute aide serait appréciée.

Répondre

0

Vous ne l'affichez pas dans vos mappages mais vraisemblablement Unit fait référence à son contrat parent. Pour supprimer une unité, vous devez définir la référence au contrat sur null et, en fonction de votre mappage, la retirer de la collection Unités du contrat.

+0

Jamie, Il n'y a pas de référence à la table Contract dans l'unité POCO ou dans le fichier HBM.XML. Le schéma créé inclut une colonne Contract_Id dans la table Unit, qui, je suppose, provient de l'élément bag/key/column name = "Contract_Id" du fichier Contract HBM.XML. Mais s'il y en avait, que se passe-t-il si je veux juste effacer toutes les tables? C'est-à-dire, faire l'équivalent d'un "DELETE FROM Units" et "DELETE FROM Contracts". Dois-je passer chaque élément dans une boucle for et retirer chaque élément? –

+0

Cette erreur se produit normalement lorsque vous supprimez un objet qui est toujours référencé par un autre objet. Lorsque l'ISession est vidée, la référence entraîne la réenregistrement de l'objet supprimé. Puisque vous avez cascade = tout ce devrait être suffisant pour supprimer les contrats et cela supprimera toutes les unités. –

+0

Je vais le vérifier quand je serai de retour au travail le lundi, mais je suis sûr que j'ai essayé d'appeler Clear sur le ContractsRepository en premier, et j'ai toujours eu la même erreur. –

Questions connexes