1

Je suis confronté à un comportement inhabituel avec le dépôt et les transactions et c'est de me rendre fou.S # arp Architecture Repository.DbContext.CommitTransaction() comportement inhabituel

J'ai deux classes POCO simples Action et Version comme suit. Il y a une relation un à plusieurs dans Action-> Version.

public class Action : Entity 
{ 
    public virtual string Name 
    { 
     get; 
     set; 
    } 

    public virtual IList<Version> Versions 
    { 
     get; 
     protected set; 
    } 

    public Action() 
    { 
     Versions = new List<Version>(); 
    } 

    public virtual void AddVersion(Version version) 
    { 
     version.Action = this; 
     Versions.Add(version); 
    } 
} 

public class Version : Entity 
{ 

    public virtual int Number 
    { 
     get; 
     set; 
    } 

    public virtual Action Action 
    { 
     get; 
     set; 
    } 

    public Version() 
    { 
    } 
} 

Maintenant, j'ai un segment de code comme suit:

var actionRep = new Repository<Action>(); 
    var versionRep = new Repository<Version>(); 

    var act1 = new Action(); 
    actionRep .SaveOrUpdate(act1); 

    using (versionRep .DbContext.BeginTransaction()) 
    { 

     var v1 = new Version(); 
     act1.AddVersion(v1); 
     //versionRep .SaveOrUpdate(v1); 
     versionRep .DbContext.CommitTransaction(); 
    } 

Dans le code ci-dessus, je suis juste en train de créer des référentiels d'action et Version. Je persiste d'abord dans un objet Action en utilisant le référentiel d'actions. Ensuite, je commence une transaction en utilisant le référentiel Version, créer une nouvelle version, définir références avec l'action, et valider la transaction sans en appelant réellement Référentiel de versions.

Le résultat est un peu étrange. L'objet version est conservé même bien que je n'ai pas appelé la méthode SaveOrUpdate sur le référentiel de versions. Si je commente la ligne act1.AddVersion (v1); Dans la transaction, , la version n'est pas persistante.

Après un peu de lutte J'ai testé le même scénario en utilisant NHibernate directement au lieu d'utiliser des référentiels de Sharp en utilisant l'architecture même cartographie Fluent/configuration (AutoPersistenceModelGenerator.Generate()). Et le résultat est attendu. L'objet version n'est pas conservé. Voici le code

var sessionFactory = CreateSessionFactory(); 
    _act1 = new Action(); 

    using(var session = sessionFactory.OpenSession()) 
    { 
     session.SaveOrUpdate(_act1); 
    } 

    using(var session = sessionFactory.OpenSession()) 
    { 
     using (var transaction = session.BeginTransaction()) 
     { 
      _v1 = new Version(); 
      _act1.AddVersion(_v1); 
      //session.SaveOrUpdate(_act1); 
      transaction.Commit(); 
     } 
    } 

La méthode CreateSessionFactory() est la suivante. Rien de compliqué

 private const string _dbFilename = "nhib_auditing.db"; 
     private static ISessionFactory CreateSessionFactory() 
     { 
      return Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
          .UsingFile(_dbFilename) 
          .ShowSql()) 
       .Mappings(m => m.AutoMappings.Add(new 
AutoPersistenceModelGenerator().Generate())) 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory(); 
     } 

maintenant Si sombody pourrait s'il vous plaît laissez-moi savoir pourquoi j'ai ce comportement . Ça me rend fou.

Juste pour que vous sachiez que je n'ai pas outrepassé le mapping pour Action et Version non plus.

En attente Nabeel

+0

tl; dr. Pouvez-vous le réduire en moins de mots? –

+0

Désolé pour ça Mauricio. En fait, je l'ai posté sur S # arp Architecture google liste de diffusion, et j'ai copié un peu collé à partir de là. – nabeelfarid

Répondre

4

Ceci est le comportement attendu si vous avez des opérations en cascade déclarées dans la cartographie. Lorsque vous avez appelé SaveOrUpdate sur act1, vous avez rendu l'objet transitoire persistant; c'est-à-dire que NHibernate le suit et l'enregistre quand la session est vidée. Une autre façon de rendre un objet persistant consiste à l'associer à un objet persistant, comme vous l'avez fait lorsque vous avez appelé act1.AddVersion(v1);. La session a été vidée lorsque la transaction a été validée, ce qui a permis de sauvegarder v1. This article explique les détails de l'utilisation d'objets persistants.

0

Par ailleurs, Voici mes deux tests avec un SharpRepositories qui est et le défaut utres avec NHibernate qui passe directement.

[TestFixture] 
    public class RepositoryTests : RepositoryTestsBase 
    { 
     protected override void LoadTestData() 
     { 
     } 

     [Test] 
     public void TestUsingSharpRespositories 
     { 
      var aRep = new Repository<Action>(); 
      var vRep = new Repository<Version>(); 

      _act1 = new Action(); 
      aRep.SaveOrUpdate(_act1); 

      using(vRep.DbContext.BeginTransaction()) 
      { 
       _v1 = new Version(); 
       _act1.AddVersion(_v1); 
       //vRep.SaveOrUpdate(_v1); 
       vRep.DbContext.CommitTransaction(); 
      } 
      _v1.IsTransient().ShouldBeTrue(); 
     } 

     [Test] 
     public void TestUsingNHibernateSession 
     { 
      var sessionFactory = CreateSessionFactory(); 
      _act1 = new Action(); 

      using(var session = sessionFactory.OpenSession()) 
      { 
       session.SaveOrUpdate(_act1); 
      } 

      using(var session = sessionFactory.OpenSession()) 
      { 
       using (var transaction = session.BeginTransaction()) 
       { 
        _v1 = new Version(); 
        _act1.AddVersion(_v1); 

        transaction.Commit(); 
       } 
      } 

      _v1.IsTransient().ShouldBeTrue(); 
     } 

     private const string _dbFilename = "nhib_db.db"; 
     private static ISessionFactory CreateSessionFactory() 
     { 
      return Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
          .UsingFile(_dbFilename) 
          .ShowSql()) 
       .Mappings(m => m.AutoMappings.Add(new 
AutoPersistenceModelGenerator().Generate())) 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory(); 
     } 

     private static void BuildSchema(Configuration config) 
     { 
      if(File.Exists(_dbFilename)) 
       File.Delete(_dbFilename); 
      new SchemaExport(config).Create(false, true); 
     } 
    } 

Je suis nouveau à Fluent NHibernate et je l'ai jamais utilisé NHibernate directement avec la cartographie xml.

En ce qui concerne le mappage, j'utilise la configuration de configuration automatique vanilla qui est configurée lorsque vous créez un nouveau projet Sharp Architecture dans Visual Studio. J'ai une convention pour hasMany comme suit:

public class HasManyConvention : IHasManyConvention 
    { 
     public void 
Apply(FluentNHibernate.Conventions.Instances.IOneToManyCollectionInstance 
instance) 
     { 
      instance.Key.Column(instance.EntityType.Name + "Fk"); 
      instance.Inverse(); 
      instance.Cascade.All(); 
     } 
    } 

Je mis à jour mon test TestUsingNHibernateSession comme suit pour tester la façon dont il se comporte, si je manipule à la fois l'action et la version en une seule session. Et devinez quoi, l'objet Version est sauvegardé, même s'il n'y a rien entre le début et la validation de la transaction.

[Test] 
    public void TestUsingNHibernateSession 
    { 
     var sessionFactory = CreateSessionFactory(); 
     _act1 = new Action(); 

     using(var session = sessionFactory.OpenSession()) 
     { 
      session.SaveOrUpdate(_act1); 
     //} 

     //using(var session = sessionFactory.OpenSession()) 
     //{ 
      _v1 = new Version(); 
      _act1.AddVersion(_v1); 
      using (var transaction = session.BeginTransaction()) 
      { 
       transaction.Commit(); 
      } 
     } 

     _v1.IsTransient().ShouldBeTrue(); 
    } 

Donc, ma conclusion est que tout cela a à voir avec la session. Si un objet A a été créé ou récupéré dans une session, puis plus tard si une nouvelle transaction commence dans cette session, alors, dès que cette transaction est validée, tous les objets transitoires ou sales associés à l'objet A sont également sauvegardés. Peu importe que les objets soient créés à l'intérieur ou à l'extérieur de Begin et Commit.

Pourriez-vous s'il vous plaît laissez-moi savoir si ils sont d'accord avec ma compréhension? Et je suppose également que l'architecture Sharp utilise une seule session nhibernate à travers chaque requête web?

En attente Nabeel

+0

Vous devriez éditer votre question pour inclure ceci plutôt que de l'afficher comme réponse –

+0

Désolé pour cela Isaac. En fait, je l'ai posté sur S # arp architecture google liste de diffusion au départ, et j'ai copié un peu collé à partir de là – nabeelfarid

Questions connexes