1

Quand je teste mes nombreux à de nombreuses classes d'une erreur se produit:Comment cartographier et tester un « plusieurs à plusieurs » à l'aide NHibernate Fluent NHibernate

System.ApplicationException: nombre effectif ne compte pas égal prévu .

Entités:

public interface IEntity 
    { 
     int Id { get; set; } 
    } 

    public abstract class Entity : IEntity 
    { 
     public virtual int Id { get; set; } 

     public virtual bool IsPersistent 
     { 
      get { return isPersistentObject(); } 
     } 

     public override bool Equals(object obj) 
     { 
      if (isPersistentObject()) 
      { 
       var persistentObject = obj as Entity; 
       return (persistentObject != null) && (Id == persistentObject.Id); 
      } 

      return base.Equals(obj); 
     } 

     public override int GetHashCode() 
     { 
      return isPersistentObject() ? Id.GetHashCode() : base.GetHashCode(); 
     } 

     private bool isPersistentObject() 
     { 
      return (Id != 0); 
     } 
    } 

    public class Team : Entity 
    { 
     public virtual string Name { get; set; } 
     public virtual ISet<Employee> Employees { get; set; } 

     public Team() 
     { 
      Employees = new HashedSet<Employee>(); 
     } 
    } 

    public class Employee : Entity 
    { 
     public virtual string LastName { get; set; } 
     public virtual string FirstName { get; set; } 
     public virtual ISet<Team> Teams { get; set; } 
     public virtual string EMail { get; set; } 

     public Employee() 
     { 
      Teams = new HashedSet<Team>(); 
     } 
    } 

Mappages:

public class TeamMap : ClassMap<Team> 
{ 
    public TeamMap() 
    { 
     // identity mapping 
     Id(p => p.Id).Column("TeamID"); 

     // column mapping 
     Map(p => p.Name); 

     // relationship mapping 
     HasManyToMany(m => m.Employees) 
      .Table("EmployeeTeam") 
      .LazyLoad() 
      .Cascade.SaveUpdate() 
      .AsSet() 
      .ParentKeyColumn("TeamID") 
      .ChildKeyColumn("EmployeeID"); 
    } 
} 

public class EmployeeMap : ClassMap<Employee> 
{ 
    public EmployeeMap() 
    { 
     // identifier mapping 
     Id(p => p.Id).Column("EmployeeID"); 

     // column mapping 
     Map(p => p.EMail); 
     Map(p => p.LastName); 
     Map(p => p.FirstName); 

     // relationship mapping 
     HasManyToMany(m => m.Teams).Table("EmployeeTeam") 
      .Inverse() 
      .Cascade.SaveUpdate() 
      .AsSet() 
      .LazyLoad() 
      .ParentKeyColumn("EmployeeID") 
      .ChildKeyColumn("TeamID"); 
    } 
} 

Test:

[TestMethod] 
public void CanCorrectlyMapEmployee() 
{ 
    var team = new List<Team> {new Team() {Name = "Team1"}}; 

    new PersistenceSpecification<Employee>(_session) 
     .CheckProperty(p => p.EMail, "Mail") 
     .CheckProperty(p => p.FirstName, "Firstname") 
     .CheckProperty(p => p.Id, 1) 
     .CheckProperty(p => p.LastName, "Lastname") 
     .CheckList(p => p.Teams,team) 
     .VerifyTheMappings(); 
} 

Que ajouter un employé ou une équipe de ma table EmployeeTeam est toujours vide.

Je l'ai testé contre SqlLite avec FNH et manuellement contre SQL Server 2008.

-ce que quelqu'un d'entre vous avez une idée pour résoudre ce problème?

modifier:

J'ai été étonné de découvrir que lorsque je crée un employé et ajouter 2 équipes à l'employé et à la charge de l'employé créé il dispose de 2 équipes. Donc ça fonctionne bien. Mais quand je regarde dans ma table Relationsip Team, tout est vide. Quelqu'un peut-il m'expliquer pourquoi?

Et quelqu'un sait comment je peux utiliser Fluent NHibernate pour tester ma relation plusieurs à plusieurs?

Merci d'avance!

Répondre

3

La carte de l'employé a un attribut inverse. Comme vous le savez probablement, cela signifie que lorsque vous sauvegardez un employé, la table de relations (EmployeeTeam) ne sera pas mise à jour. Pour ajouter/supprimer de nouvelles informations de relation, vous devez ajouter un employé à l'équipe et enregistrer l'équipe.

Ainsi, dans votre cas - ne pas tester beaucoup à beaucoup du côté de l'employé, le tester sur le côté de l'équipe. (Si vous souhaitez que NHibernate ajoute des enregistrements lorsque vous ajoutez une équipe à un employé, vous devez inverser les attributs "Inverse" - donner à l'équipe, pas à l'employé, mais ensuite - la même histoire avec l'entité Team).

Pourquoi avez-vous été en mesure de charger des employés avec des équipes? En raison du cache au niveau de la session. Vous avez probablement enregistré et chargé Employee dans la même ISession - cela signifie que NHibernate vous a renvoyé exactement la référence au même objet, sans le charger depuis la base de données. Essayez d'enregistrer & en chargeant deux sessions différentes et vous ne verrez aucune équipe dans Employee.Teams.

Remarque: Il est recommandé de créer des méthodes qui renforcent la cohérence entre les relations plusieurs-à-plusieurs, c'est-à-dire - lorsque vous ajoutez une équipe à un employé, un employé est ajouté à l'équipe, sth. comme ceci:

class Employee 
{ 
    // ... 
    public void AddTeam(Team team) 
    { 
    // check for null, etc. 

    Teams.Add(team); 
    team.Employees.Add(this); 
    } 
} 

et méthode très simillar dans la classe d'équipe.

+0

bien me manque une fonction de citation sur stackoverflow ... « [...] En raison de cache de niveau session Vous avez probablement enregistré et employé chargé dans le même ISession -. Cela signifie que NHibernate vous faites référence retourné exactement à la même objet, sans le charger depuis le db. " Ce n'est pas correct.J'ai testé cela et oui NHibernate met en cache mes objets mais j'ai effacé le cache et chargé ensuite mes objets. En outre, j'ai utilisé SQL Server Profiler et j'ai vu une requête de sélection avec LEFT OUTER JOIN. Ainsi, la récupération et l'enregistrement fonctionnent, étrangement. Mais je vais essayer vos conseils. Merci pour maintenant. – Rookian

+0

Le problème était que la relation était vide, parce que je n'ai pas vidé la session. Maintenant, l'employé et l'équipe peuvent être enregistrés correctement. – Rookian

Questions connexes