2012-09-13 1 views
0

Je les entités mise en jachère:Collection n'est pas sélectionnée avec NHibernate-caching

Personne Société

Et puis, il y a une entité PersonCompany qui fait une relation entre personne et société

Mapping pour personne est:

public class PersonMap : SubclassMap<Person> { 
    public PersonMap() { 
     this.Table("Person"); 
     this.KeyColumn("Id"); 
     this.HasMany(x => x.PersonCompanys).AsSet().KeyColumn("PersonId").Fetch.Select().Inverse().Cascade.Delete(); 
    } 
} 

Société:

public class CompanyMap : SubclassMap<Company> { 
    public CompanyMap() { 
     this.Table("Company"); 
     this.KeyColumn("Id"); 
     this.HasMany(x => x.PersonCompanys).AsSet().KeyColumn("CompanyId").Fetch.Select().Inverse().Cascade.None(); 
    } 
} 

et PersonCompany:

public class PersonCompanyMap : ClassMap<PersonCompany> { 
    public PersonCompanyMap() { 
     this.Table("PersonCompany"); 

     this.Version(x => x.ObjectVersion); 
     this.Id(x => x.Id).GeneratedBy.Assigned(); 
     this.References(x => x.Company).Column("CompanyId").Fetch.Select(); 
     this.References(x => x.Person).Column("PersonId").Fetch.Select(); 
    } 
} 

SecondLevel-Caching est activé général et pour chaque entité avec les conventions. Aussi Caching pour la PersonCompanys-Collection:

public class CachableConventions : IClassConvention, IHasManyConvention, IHasManyToManyConvention { 
    private static readonly Type[] notCachableTypes = new[] {typeof(Word), typeof(ActivityWord), typeof(DbVersion), typeof(Deleted), typeof(ExchangeSyncState), typeof(Synchronizer), typeof(SerialletterField)}; 

    public void Apply(IClassInstance instance) { 
     if (Array.IndexOf(notCachableTypes, instance.EntityType) >= 0) { 
      return; 
     } 
     instance.Cache.ReadWrite(); 
    } 

    public void Apply(IManyToManyCollectionInstance instance) { 
     if (Array.IndexOf(notCachableTypes, instance.ChildType) >= 0) { 
      return; 
     } 
     instance.Cache.ReadWrite(); 
    } 
    public void Apply(IOneToManyCollectionInstance instance) { 
     if (Array.IndexOf(notCachableTypes, instance.ChildType) >= 0) { 
      return; 
     } 
     instance.Cache.ReadWrite(); 
    } 
} 

Maintenant, je crée une nouvelle personne et après l'enregistrement, une nouvelle société, puis-je ajouter un PersonCompany-Record à la PersonCompanies-Collection.

Lorsque je sélectionne la personne créée, la collection PersonCompanys est vide. Lorsque je fais de même sans SecondLevel-Caching, PersonCompanys-Collection contient l'entité créée.

Quelqu'un sait-il, ce qui peut mal tourner ici?

Modifier - Informations supplémentaires:

ces étapes sont à l'origine du problème:

  1. créer une nouvelle personne Session.Save(person)
  2. charge la personne person = Session.Get(person.Id)
  3. get personCompany de la personne avec personCompany = person.PersonCompany.FirstOrDefault() (ce sera vide)
  4. Créer une nouvelle entrée avec PersonCompany-Session.Save(new PersonCompany(Guid.NewGuid()) {Person = person}))
  5. charge la personne person = Session.Get(person.Id)
  6. maintenant, person.PersonCompany retourne une liste vide.

Lorsque je ne fais pas l'étape 3, tout fonctionne très bien.

+0

Mon sentiment est que cela n'a rien à voir avec votre mise en cache. Sans voir ce que vous faites pendant la création des objets Person, Company et PersonCompany, je ne peux pas vous aider. –

+0

Lorsque je désactive le deuxième niveau, il fonctionne correctement. Peut-être que le problème est de savoir comment j'associe la personne à la nouvelle PersonCompany. Je fais personCompany.Person = person et l'appel Session.Insert (personCompany) – BennoDual

+0

Tout d'abord, sauf si vous avez une très bonne raison d'utiliser Session.Insert, vous devriez utiliser Session.SaveOrUpdate (...). Si je me souviens bien, Session.Insert évite beaucoup de la mise en cache interne. –

Répondre

0
  1. voir obove
  2. voir obove
  3. get personCompany de la personne personCompany = person.PersonCompany.FirstOrDefault() (ce sera vide)

    ce initialisera la collection à une collection vide

  4. Créer une nouvelle PersonCompany-Entry avec Session.Enregistrer (nouveau PersonCompany (Guid.NewGuid()) {personne = personne}))

    va créer un enregistrement dans la base de données PersonCompany

  5. charge la personne avec personne = Session.get (person.Id)

    va simplement retourner l'objet personne en cache, donc c'est basiquement « ne rien faire »

  6. maintenant, person.PersonCompany retourne une liste vide

depuis que la collection a été initialisée à en collection vide à l'étape 3, il reviendra juste cela. nhibernate n'émettra pas un autre select pour savoir si quelque chose a changé. si elle serait-il écarterait probablement des changements locaux ou produire des conflits et il ne serait pas très efficace

do

  • session.Clear(); comme étape 3b ou
  • session.Refresh(person); comme étape 5

alors il fonctionne comme prévu

+0

Lorsque je fais une session.Refresh (personne) comme étape 5, ça va fonctionner. Je me demande, pourquoi est-ce nécessaire, parce que Session est toujours une nouvelle session ouverte. NHibernate-Second-Level Cache ne devrait-il pas le faire pour moi? - Lorsque je sauvegarde une nouvelle PersonCompany, puis l'ajouter à PersonCompanies-Liste des Personnes mises en cache? Quand non, existe-t-il un moyen général de résoudre ce problème? – BennoDual

+0

le deuxième cache lvl ne mettra pas à jour vos objets par magie car ce n'est peut-être pas ce que vous voulez ou il y a des conditions de course et autres. Il serait également impossible de savoir où insérer dans la collection lorsque la collection est mappée avec "order by", "sql", "formula" et autres. Un service de publication-abonnement dans l'application notifiant tout pour rafraîchir leurs personnes serait le meilleur OMI – Firo