S#arp Architecture Repository.DbContext.CommitTransaction()异常行为

时间:2010-06-22 22:05:37

标签: nhibernate fluent-nhibernate s#arp-architecture automapping

我正面临着Repository和Transactions的异常行为 它让我很生气。

我有两个简单的POCO类Action和Version如下。有 来自Action->版本的一对多关系。

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和Version存储库。 首先,我使用Action Repository持久化Action对象。然后我开始 使用Version repository的事务,创建一个新版本,set 带有Action的引用,并且在没有的情况下提交事务 实际上调用版本库。

结果有点奇怪。版本对象甚至可以持久化 虽然我没有在版本库上调用SaveOrUpdate方法。如果 我注释掉了行act1.AddVersion(v1);在交易中, 然后版本不会持久化。

经过一番努力,我使用NHibernate测试了相同的场景 直接而不是使用Sharp Architecture存储库使用相同的 流畅的映射/配置 (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()方法如下。没什么复杂的

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

现在如果sombody可以请让我知道为什么我这样做 行为。它让我很生气。

只是为了让你知道我没有覆盖Action和的映射 版本要么。

等待 纳贝尔

2 个答案:

答案 0 :(得分:4)

如果您在映射中声明了级联操作,则这是预期的行为。当您在act1上调用SaveOrUpdate时,您使瞬态对象持久化;也就是说,NHibernate会跟踪它并在刷新会话时保存它。使对象持久化的另一种方法是将其与持久对象相关联,就像调用act1.AddVersion( v1 );时所做的那样。提交事务时会话被刷新,因此保存了v1。 This article解释了使用持久对象的细节。

答案 1 :(得分:0)

顺便说一下,这是我用SharpRepositories进行的两次测试 失败了,以及NHibernate Directly正在通过。

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

我是Fluent NHibernate的新手,我从未直接使用NHibernate进行xml映射。

就映射而言,我正在使用在Visual Studio中创建新的Sharp Architecture项目时设置的vanilla自动配置。我有一个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测试,以测试在单个会话中操作Action和Version时的行为方式。并猜测,即使在事务的开始和提交之间没有任何内容,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之内或之外创建了更好的对象。

如果他们同意我的理解,有人可以告诉我吗?我还假设Sharp架构在每个Web请求中使用单个nhibernate会话?

等待 纳贝尔