S # arp Архитектура Repository.DbContext.CommitTransaction () необычное поведение - PullRequest
1 голос
/ 23 июня 2010

Я сталкиваюсь с необычным поведением в репозитории и транзакциях, и это меня бесит.

У меня есть два простых класса 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 иВерсии репозиториев.Сначала я сохраняю объект 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();
        }

Теперь, если кто-то может, пожалуйста, дайте мне знать, почему у меня такое поведение.Это сводит меня с ума.

Просто чтобы вы знали, что я не переопределил сопоставление для Action и Version.

В ожидании Набиль

Ответы [ 2 ]

4 голосов
/ 23 июня 2010

Это ожидаемое поведение, если у вас есть каскадные операции, объявленные в отображении.Когда вы вызывали SaveOrUpdate на act1, вы делали временный объект постоянным;то есть, NHibernate отслеживает это и сохранит это, когда сеанс сброшен.Другой способ сделать объект постоянным - это связать его с постоянным объектом, как вы это делали, когда вызывали act1.AddVersion( v1 );.Сессия была сброшена, когда транзакция была зафиксирована, поэтому v1 был сохранен. Эта статья объясняет детали работы с постоянными объектами.

0 голосов
/ 23 июня 2010

Кстати, вот мои два теста, один с 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.

Что касается сопоставления, я использую конфигурацию автоматического преобразования, которая настраивается при создании нового проекта Sharp Architecture в visual studio.У меня есть соглашение для 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 and Commit.

Может кто-нибудь сообщить мне, согласны ли они с моим пониманием?И я также предполагаю, что архитектура Sharp использует один сеанс nhibernate для каждого веб-запроса?

В ожидании Набиль

...