How to cascade Save to CompositeId in NHibernate?

I have a simple table with three tables with many relationships.

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

Relevant classes:

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 */ }
}

I made comparisons with 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");
    }
}

So now I want to do something like this

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

But on SaveOrUpdate, I get a TransientObjectException. Therefore, to pass this, I need to save SaveOrUpdate A and B before saving AB. But it seems that there should be another way to save these objects in one SaveOrUpdate.

Is there a way to point to Cascade A and B in an AB conversion during a save operation?

UPDATE:

I deleted the AB reference list in class A for clarity. Originally it was:

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

Thanks!

+3
source share
3 answers

nhibernate. , (, ).

, . (-- ) CompositeId Id AB AB. A B .

+2

, AB? , "AB" ...

: NHibernate.

Fluent NHibernate, , :

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

( , , collectionmapping Cascade, , )

0

I really managed to make it work very easily, and the code looks too much NOT DRY!

Here is what my case looked like:

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

I hope this helps someone look for the same problem in the future.

0
source

Source: https://habr.com/ru/post/1717621/


All Articles