Как каскадно сохранить с CompositeId в NHibernate? - PullRequest
3 голосов
/ 14 сентября 2009

У меня есть простая БД из трех таблиц с отношением «многие ко многим».

A(id, Name)
B(id, Name)
AB(AId, BId) references A and B

Соответствующие классы:

public class A
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

public class B
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

public class AB
{
    public virtual A A { get; set; }
    public virtual B B { get; set; }
    public override bool Equals(object obj) { /* routine */ }
    public override int GetHashCode() { /* routine */ }
}

Я сделал сопоставления с помощью Fluent NHibernate:

public class AMap : ClassMap<A>
{
    public AMap()
    {
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Name);
    }
}

public class BMap : ClassMap<B> { /* The same as for A */ }

public class ABMap : ClassMap<AB>
{
    public ABMap()
    {
        CompositeId()
            .KeyReference(x => x.A, "AId")
            .KeyReference(x => x.B, "BId");
    }
}

Так что теперь я хочу иметь возможность сделать что-то вроде этого

var a = new A { Name = "a1" };    
var b = new B { Name = "b1" };    
var ab = new AB { A = a, B = b };

//session.SaveOrUpdate(a);
//session.SaveOrUpdate(b);
session.SaveOrUpdate(ab);

Но при SaveOrUpdate Я получаю TransientObjectException . Поэтому, чтобы пройти через него, мне нужно SaveOrUpdate A и B перед сохранением AB. Но, похоже, должен существовать другой способ сохранения этих объектов в одном SaveOrUpdate .

Есть ли способ указать в отображении AB на Каскад A и B при операции сохранения?

UPDATE:

Я удалил список ссылок AB в классе A для ясности. Изначально это было:

public class A
{
    public A()
    {
        LinkToB = new List<AB>();
    }

    public virtual int Id { get; set; }
    public virtual string Name { get; set }
    public virtual IList<AB> LinkToB { get; private set; }
}

public class AMap : ClassMap<A>
{
    public AMap()
    {
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Name);

        HasMany(x => x.LinkToB)
            .KeyColumn("AId")
            .Inverse()
            .Cascade.All()
            .AsBag();
    }
}

// inside the transaction
var a = new A { Name = "a1" };
var b = new B { Name = "b1" };

a.LinkToB.Add(new AB { A = a, B = b });
// session.SaveOrUpdate(b);
session.SaveOrUpdate(a);

Спасибо!

Ответы [ 3 ]

2 голосов
/ 16 сентября 2009

Я задавал этот вопрос в группе пользователей nhibernate. И ответ состоял в том, что нет никакого способа каскадировать какую-либо операцию с использованием Composite-ID (возможно, в будущих версиях это будет возможно).

Итак, я сделал обходной путь. Я поместил две ссылки (много-к-одному с каскадом) вместо CompositeId и добавил Id в таблицу AB и сущность AB. Теперь он работает, а сущности A и B. каскадные.

0 голосов
/ 18 октября 2009

Мне действительно удалось заставить его работать очень легко, и код выглядит слишком много НЕ СУХОЙ!

Вот как выглядел мой случай:

public class MappingSample : ClassMap<DomainClass>
{
    public MappingCvTheme()
    {
        CompositeId()
            .KeyProperty(x => x.SomeProperty)
            .KeyReference(x => x.SomeReferencedObjectProperty);

        //here comes the trick, repeat the reference code:
        References(x => x.SomeReferencedObjectProperty).Cascade.All();
    }
}

Я надеюсь, что это поможет кому-то искать такую ​​же проблему в будущем.

0 голосов
/ 14 сентября 2009

Просто примечание, но почему вы создали класс AB? Если отношения между этими двумя классами не имеют каких-либо дополнительных свойств, тогда ваш класс 'AB' не нужен ...

Чтобы ответить на ваш вопрос: вы можете определить каскадные параметры для отношений в NHibernate.

В Fluent NHibernate, я думаю, вам придется сделать это так:

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
       HasMany(x => x.Bars).Cascade.AllDeleteOrphan();
    }
}

(обратите внимание, что вы должны применить его к вашей ситуации, но сопоставление коллекции возвращает свойство Cascade, чтобы вы могли определить, какую технику каскадирования вы хотите применить)

...