Беглый эталонный NHibernate / каскад много-к-одному не работает

У меня есть некоторые проблемы с каскадом всех (сирота) и удалить старый объект из базы данных.

Пример: у меня есть класс A, который содержит объект класса B. Теперь, когда я создаю объект класса A и сохраняю его, все работает нормально. Когда я вызываю метод SetValueOfB(int i) и снова сохраните объект A, старый объект B все еще находится в базе данных.

Должна ли связь между классами всегда быть направленной (для каждого HasMany/Reference/HasOne...)? (Но объект b ничего не знает об объекте a)

Есть ли способ решить проблему с однонаправленной ассоциацией?

Нужно ли сопоставление один-к-одному? Поскольку объект B может принадлежать только объекту A (A является параметром, а B является значением).

Вот неудачный тест:

using System.Collections.Generic;
using System.Data;
using System.IO;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;

namespace ReferenceCascade.Test
{
public class CascadeTest
{
    private const string DbFile = "firstProject.db";

    [Test]
    public void checkCascadeAll()
    {
        var sessionFactory = CreateSessionFactory();

        A testee = new A(new B(1));

        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {

                session.SaveOrUpdate(testee);

                transaction.Commit();
            }
        }

        testee.SetValueOfB(2);

        using (var session = sessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                session.SaveOrUpdate(testee);

                transaction.Commit();
            }
        }

        using (var session = sessionFactory.OpenSession())
        {
            using (session.BeginTransaction())
            {
                IList<B> stores = session.CreateCriteria(typeof(B))
                  .List<B>();

                Assert.That(stores.Count, Is.EqualTo(1));
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
          .Database(SQLiteConfiguration.Standard.UsingFile(DbFile).IsolationLevel(IsolationLevel.ReadCommitted))
          .Mappings(m =>
            m.FluentMappings.AddFromAssemblyOf<CascadeTest>())
          .ExposeConfiguration(BuildSchema)
          .BuildSessionFactory();
    }

    private static void BuildSchema(Configuration config)
    {
        // delete the existing db on each run
        if (File.Exists(DbFile))
        {
            File.Delete(DbFile);
        }

        // this NHibernate tool takes a configuration (with mapping info in)
        // and exports a database schema from it
        new SchemaExport(config)
          .Create(false, true);
    }
}

public abstract class Entity
{
    public const long InitialId = 0;

    private readonly long _id;

    protected Entity()
    {
        _id = InitialId;
    }

    public virtual long Id
    {
        get { return _id; }
    }
}

public class A : Entity
{
    private B _b;

    public A()
    {
    }

    public A(B b)
    {
        _b = b;
    }

    public virtual void SetValueOfB(int i)
    {
        _b = new B(i);
    }

    public virtual B B
    {
        get { return _b; }
    }
}

public class B : Entity
{
    private readonly int _i;

    public B()
    {
    }

    public B(int i)
    {
        _i = i;
    }

    public virtual int I
    {
        get { return _i; }
    }
}

public class EntityMap<T> : ClassMap<T> where T : Entity
{
    public EntityMap()
    {
        Id(x => x.Id).GeneratedBy.HiLo("33878").Access.CamelCaseField(Prefix.Underscore);
    }
}

public class AMap : EntityMap<A>
{
    public AMap()
    {
        Table("A");
        References(x => x.B).Not.LazyLoad().Cascade.All().Access.CamelCaseField(Prefix.Underscore);
    }
}

public class BMap : EntityMap<B>
{
    public BMap()
    {
        Table("B");
        Map(x => x.I).Not.LazyLoad().Access.CamelCaseField(Prefix.Underscore);
    }
}

}

Или вот проект: против проекта

1 ответ

Мы не нашли способ решить проблему. В NHibernate версии 4.1 проблема будет исправлена, и можно использовать cascade=all-delete-orphan со многими-к-одному. Смотрите здесь: https://nhibernate.jira.com/browse/NH-1262

Другие вопросы по тегам