1

I have a one-to-one mapping which I'm trying to express with Fluent NHibernate mappings. I know there are a LOT of similar questions/answers on the web but after hours I'm struggling to find an answer to my specific question.

I have a Member and Subscription object. A member can have 0..1 Subscriptions and a subscription instance can only ever pertain to a single member.

Here are my classes:

public class Member
{
    public Subscription Subscription { get; set; }
}

public class Subscription
{
    public Member Member { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime FinishDate { get; set; }
}

Here are my mappings (fluent):

For Member:

mapping.HasOne(member => member.Subscription)
    .PropertyRef(subscription => subscription.Member).Cascade.SaveOrUpdate();

For Subscription:

mapping.References(subscription => subscription.Member)
   .Unique().Cascade.None();

There are a few requirements but I can't seem to fulfill them all:

  • That saving a Member cascades to Subscription.
  • Deleting a Subscription breaks the association on the Member.
  • Deleting a Subscription doesn't delete the Member.

If I set Cascade on Member the Subscription is saved, but deleting a Subscription throws an ObjectDeletedException.

Why can't NHibernate automatically remove the association to Subscription first, before applying the cascade on Member?

4

1 に答える 1

2

ここでの基本的な問題は、これは 1 対 1 の関係ではなく、多側が 0 または 1 に制限された 1 対多であるということです。1 対 1 の関係では、両方のエンティティが同じプライマリを持つ必要があります。キーであり、これは明らかにここでは当てはまりません。この質問を参照してください。

私はこれを次のようにモデル化します

public class Member
{
    private ICollection<Subscription> _subscriptions;

    public Name() { _subscriptions = new HashSet<Subscription>(); }

    public Subscription Subscription
    {
        get { return _subscriptions.SingleOrDefault(); }
        set
        {
            _subscriptions.Clear(); // may want to check if it contains value first
            value.Member = this; // assuming bidirectional association
            _subscriptions.Add(value); // null check value first
        }
    }
}

mapping.HasMany<Subscription>(Reveal.Member<Member>("_subscriptions"))
    .KeyColumn("MemberId")
    .AsSet().Inverse().Cascade.AllDeleteOrphan();

また、property-ref を適切に使用しているとは思いませんが、1 対 1 を不適切にマッピングしていた可能性があります。

于 2013-01-18T12:58:02.980 に答える