1

我面临着一个不寻常的行为,存储库和事务 ,它让我发疯。S#arp Architecture Repository.DbContext.CommitTransaction()不寻常的行为

我有两个简单的POCO类Action和Version,如下所示。从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() 
    { 
    } 
} 

现在我有一个代码段如下:

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(); 
    } 

在上面的代码,我只是在创建动作和版本库。 首先我使用Action Repository持久化一个Action对象。然后我开始使用版本存储库开始 事务,创建新版本,设置 引用与操作,并提交实际调用版本存储库的 事务。

结果有点奇怪。虽然我尚未在版本存储库上调用SaveOrUpdate方法,但版本对象仍然保留,即使是 也是如此。如果 我注释掉act1.AddVersion(v1);在交易中, ,那么版本不会持续。

后一点斗争的我测试使用NHibernate ,而不是直接使用利用相同 流利映射/配置 夏普架构库相同的情况下(AutoPersistenceModelGenerator.Generate())。结果如预期的 。版本对象不会持久。这里是代码

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(); 
     } 
    } 

CreateSessionFactory()方法如下。如果sombody可以请让我知道为什么我有这个 行为没有什么复杂的

 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(); 
     } 

现在。它让我发疯。

只是为了让你知道我还没有重写Action和 版本的映射。

等待 纳比尔

+0

tl; dr。你能用更少的话来缩小它的范围吗? – 2010-06-22 22:39:58

+0

对不起,毛里西奥。我实际上发布它在S#arp架构谷歌邮件列表,并且我有点从那里复制。 – nabeelfarid 2010-06-23 10:36:13

回答

4

这是预期的行为,如果你已经在级联的映射申报操作。当您在act1上调用SaveOrUpdate时,您使瞬态对象保持不变;也就是说,NHibernate正在跟踪它,并在会话刷新时保存它。使对象持久化的另一种方法是将其与持久对象关联起来,就像您在拨打act1.AddVersion(v1);时所做的那样。交易提交时,会话被刷新以保存v1。 This article解释了使用持久对象的细节。

0

顺便说一句,这里是我的两个测试一个与SharpRepositories这是 失败,与NHibernate直接被传递疗法。

[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); 
     } 
    } 

我是新来的流利NHibernate,我从来没有直接使用NHibernate的XML映射。

就映射而言,我使用的是在Visual Studio中创建新的Sharp Architecture项目时设置的vanilla automapping配置。我有一个的hasMany约定如下:

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

我更新了我的TestUsingNHibernateSession如下测试,以测试它的行为,如果我在一个会议上操纵动作都和版本。并猜测Version对象被保存的是什么,即使事务的开始和提交之间没有任何内容。

[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(); 
    } 

所以我的结论是,它的一切都与会议。如果在会话中创建或检索到对象A,并且稍后如果在该会话内开始新的事务,则在该事务提交后,与对象A相关联的所有瞬态或脏对象也被保存,否在Begin和Commit之内或之外创建其他对象。

任何人都可以让我知道他们是否同意我的理解?我还假设夏普架构通过每个Web请求使用单个nhibernate Session?

等待 纳比尔

+0

您应该编辑您的问题以包含此内容,而不是将其作为回答发布 – 2010-06-22 22:08:44

+0

对不起,艾萨克。实际上,我最初将它发布在S#arp架构谷歌邮件列表中,并且我从那里粘贴了一个副本 – nabeelfarid 2010-06-23 10:37:11