简体   繁体   English

如何在NHibernate中使用CompositeId级联保存?

[英]How to cascade Save with CompositeId in NHibernate?

I have a simple three table DB with many-to-many relation. 我有一个简单的三表DB,具有多对多的关系。

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

The corresponding 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 have made mappings with Fluent NHibernate: 我已经使用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 be able 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 do get TransientObjectException . 但是在SaveOrUpdate上,我确实得到了TransientObjectException So to pass over it I need to SaveOrUpdate A and B before saving the AB. 因此,为了传递它,我需要在保存AB之前SaveOrUpdate A和B. But it seems that there should be the other way to persist these objects in a single SaveOrUpdate . 但似乎应该有另一种方法将这些对象保存在单个SaveOrUpdate中

Is there any way to point in AB mapping to Cascade A and B on save operation? 在保存操作中,是否有任何方法可以将AB映射指向级联 A和B?

UPDATE: 更新:

I removed the List of AB links in A class for clarity. 为清楚起见,我删除了A类中的AB链接列表。 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);

Thank you! 谢谢!

I did ask this question at nhibernate user group. 我确实在nhibernate用户组问了这个问题。 And the answer was that there is no way to cascade any operation using composite-id (maybe in the future releases it will be possible). 答案是没有办法使用composite-id级联任何操作(可能在将来的版本中它是可能的)。

So I made a workaround. 所以我做了一个解决方法。 I placed two References (many-to-one with cascading) instead of CompositeId and added Id to the AB table and AB entity. 我放置了两个引用(多个一对一的级联)而不是CompositeId,并将Id添加到AB表和AB实体。 Now it's working and A and B entities are cascading. 现在它正在工作,A和B实体正在级联。

Just a side-note, but why did you create a class AB ? 只是旁注,但为什么要创建AB类? If the relationship between these 2 classes does not have any extra properties, then your class 'AB' is not necessary ... 如果这两个类之间的关系没有任何额外的属性,那么你的班级'AB'就没有必要......

To answer your question: you can define cascade options on a relationship in NHibernate. 回答你的问题:你可以在NHibernate中的关系上定义级联选项。

In Fluent NHibernate, I guess you'll have to do it like this: 在Fluent NHibernate中,我想你必须这样做:

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

(note that you have to apply it to your situation, but the collectionmapping returns a property Cascade, so you can define which cascading technique you wish to apply) (请注意,您必须将其应用于您的情况,但collectionmapping返回属性Cascade,因此您可以定义要应用的级联技术)

I actually managed to get it working 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 it helps somebody looking for the same issue in the future. 我希望它有助于某人在将来寻找同样的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM