2

私はAggregateの設計原則に従おうとしていますが、助けが必要な状況を考え出しました。私の集約ルートはCustomerオブジェクトです。Customerオブジェクトには、オブジェクトの子コレクションとオブジェクトAddressの子コレクションがありContactます。

Aは、集合体の下Contactへの参照を持つことができます。オブジェクトには一意のオブジェクトがあり、オブジェクトにはローカルIDがあるため、データベースの主キーはandになります。AddressCustomerCustomerIDAddressContactCustomerIdAddressId

簡略化されたクラスは次のとおりです。

public class Customer : AggregateRoot {
    public virtual int CustomerId { get; protected set; }
    public virtual IList<Address> Addresses { get; protected set; }
    public virtual IList<Contact> Contacts { get; protected set; }
}
public class Address : Entity {
    public Address(Customer customer, int addressId) {
        this.Customer = customer;
        this.AddressId = addressId;
    }

    public virtual Customer Customer { get; protected set; }
    public virtual int AddressId { get; protected set; }
}
public class Contact : Entity {
    public Contact(Customer customer, int contactId) {
        this.Customer = customer;
        this.ContactId = contactId;
    }

    public virtual Customer Customer { get; protected set; }
    public virtual int ContactId { get; protected set; }
    public virtual Address Address { get; set; }
}

データベースには、次のようなテーブルがあります。

お客様

CustomerId int identity PK

住所

CustomerId int not null PK,FK
AddressId int not null PK

コンタクト

CustomerId int not null PK,FK
ContactId int not null PK
AddressId int null FK

私の問題は、FluentNHibernateを使用してエンティティをマッピングしようとしたときに発生します。Addressオブジェクトにはとの複合キーがあるCustomerIdため、AddressIdNHibernateはCustomerId連絡先テーブルの列を再利用しません。集計を保存しようとすると、パラメーターよりも値が多いという例外が発生します。CustomerIdこれは、Addressオブジェクトに複合IDがあり、オブジェクトと列を共有していないために発生しContactます。

これを回避するために私が見ることができる唯一の方法はAddressCustomerId、テーブルに列を追加することですが、現在、とは同じ値であるContactため、重複する列があります。とにかくこの振る舞いの周りにありますか?CustomerIdAddressCustomerId

4

2 に答える 2

1

AddressとContactのどちらもCustomerアグリゲートの外部にIDを持たない場合は、コンポーネントコレクションとしてマッピングする必要があります。また、顧客と住所の関係と顧客と連絡先の関係を双方向にする必要がありますか?そして、addressIdとcontactIdが必要ですか?モデルが単純化されている場合、これは機能します。

public class Customer
{
    public virtual int CustomerId { get; protected set; }
    public virtual IList<Address> Addresses { get; protected set; }
    public virtual IList<Contact> Contacts { get; protected set; }
}

public class Address
{
    public string Street1 { get; private set; }
    public string Street2 { get; private set; }
    public string City { get; private set; }
    public string Region { get; private set; }
}

public class Contact
{
    public string Name { get; private set; }
    public string Email { get; private set; }
    public virtual Address Address { get; set; }
}

public class CustomerMap : FluentNHibernate.Mapping.ClassMap<Customer>
{
    public CustomerMap()
    {
        Table("Customers");
        Id(x => x.CustomerId);
        HasMany(x => x.Addresses)
            .Table("CustomerAddresses")
            .KeyColumn("CustomerId")
            .Component(m =>
            {
                m.Map(x => x.Street1);
                m.Map(x => x.Street1);
                m.Map(x => x.City);
            });
        HasMany(x => x.Contacts)
            .Table("CustomerContacts")
            .KeyColumn("CustomerId")
            .Component(m =>
            {
                m.Map(x => x.Name);
                m.Map(x => x.Email);
                m.Component(x => x.Address, ma =>
                {
                    ma.Map(x => x.Street1);
                });
            });
    }
}

マッピングでは、アドレスと連絡先のコレクションがコンポーネントとしてマッピングされます。これは、独自のIDを持っている必要がないため、個々のマッピングクラスがないことを意味します。ただし、このモデルでは、連絡先のアドレスは連絡先データ自体と同じ行に格納されます。これは、(より正規化されたモデルとは対照的に)優れたモデルであると私は信じています。

于 2012-08-03T04:27:24.180 に答える
0

私の知る限り、NHibernateでは列を共有する方法はありません。結局、数年前から使用しているソリューションを使用することになりました。NHibernateのIDとしてGUIDを使用し、intサロゲートキーを使用してクエリを実行します。このソリューションは私にとってはうまく機能していますが、データベースに追加された無駄の一部を減らしたかっただけです。

于 2012-08-13T11:27:23.833 に答える