0

NHibernate の新機能。この従来のテーブルをマップする方法に頭を悩ませています。

CREATE TABLE [dbo].[CmnAddress](
[addressId] [int] NOT NULL,
[objectType] [varchar](63) NULL,
[objectId] [int] NULL,
[addressType] [varchar](7) NULL,
[recordStatus] [char](1) NULL,
[fromDate] [int] NULL,
[toDate] [int] NULL,
[onStreet] [varchar](254) NULL,
[atStreet] [varchar](254) NULL,
[unit] [varchar](30) NULL,
[city] [varchar](254) NULL,
[state] [varchar](30) NULL,
[zipCode] [varchar](30) NULL,
)

Person クラスにマップした「CmnPerson」テーブルもあります。Person クラスに Addresses のリストを含める必要があります。objectType 列には「CmnPerson」が含まれ、objectId フィールドは Person.Id ("CmnPerson.personId") フィールドと一致します。

また、後で、objectType 列に「CmnContact」が含まれる Addresses のリストも含む Contact クラスを作成する必要があります。

サブカラムを区別して Any マッピングまたは class-hierarchy-per-table を使用する必要があるかどうかを判断するのに非常に苦労していますか? または、それらのいずれかが私のニーズを満たしている場合。

この Address クラスをマップする方法を誰かに教えてもらえますか? 流暢な構成が望ましいでしょう。

追加情報:

次のクラスとマッピングはほとんど機能しますが、Addresses リストは、objectType フィールドの値に関係なく、一致する objectId を持つ CmnAddress テーブルからすべての行を返します。Person.Addresses の HasMany マッピングで ApplyFilter を使用できると思いますが、それは「正しい」方法ではないようです。

追加情報: DiscriminateSubClassesOnColumn(...) の呼び出し後に AlwaysSelectWithValue() をチェーンすることで、この最後の問題を解決できました。

public class Person
{
    public virtual int Id { get; private set; }
    public virtual string LastName { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string MiddleName { get; set; }
    public virtual string Gender { get; set; }

    public virtual IList<PassClient> PassClients { get; set; }
    public virtual IList<PersonAddress> Addresses { get; set; }
}

public class PersonMap : ClassMap<Person>
{
    public PersonMap() {
        Table("CmnPerson");
        Id(x => x.Id).Column("personId");
        Map(x => x.LastName);
        Map(x => x.FirstName);
        Map(x => x.MiddleName);
        Map(x => x.Gender);

        HasMany(x => x.PassClients).KeyColumn("personId");
        HasMany(x => x.Addresses).KeyColumn("objectId");
    }
}

abstract public class Address
{
    public virtual int Id { get; private set; }
    public virtual string StreetNo { get; set; }
    public virtual string OnStreet { get; set; }
    public virtual string Unit { get; set; }
    public virtual string City { get; set; }
    public virtual string State { get; set; }
    public virtual string ZipCode { get; set; }
}

public class PersonAddress : Address { 
    public virtual Person Person { get; set; }
}

public class AddressMap : ClassMap<Address>
{
    public AddressMap() {
        Table("CmnAddress");

        Id(x => x.Id).Column("addressId");
        Map(x => x.StreetNo);
        Map(x => x.OnStreet);
        Map(x => x.Unit);
        Map(x => x.City);
        Map(x => x.State);
        Map(x => x.ZipCode);

        DiscriminateSubClassesOnColumn("objectType").AlwaysSelectWithValue();
    }
}

public class PersonAddressMap : SubclassMap<PersonAddress>
{
  public PersonAddressMap() {
        DiscriminatorValue("CmnPerson");

        References(x => x.Person).Column("objectId");
  }
}
4

3 に答える 3

1

申し訳ありませんが、流暢なマッピングに慣れていませんが、それを行う1つの方法は次のとおりです。

  • objectTypeを除く、テーブル内のすべての列に対応するプロパティを持つAddress抽象クラスを作成します。
  • Addressを拡張するPersonAddressクラスを作成する
  • Addressを拡張するContactAddressクラスを作成する

  • 識別子列として宣言するobjectTypeを除いて、CmnAddressのすべての列を通常の方法でAddressクラスのプロパティにマップします。

  • 識別子値「CmnPerson」を使用して、 PersonAddressをAddressのサブクラスとしてマップします。
  • 「CmnContact」の識別子値を持つAddressのサブクラスとしてContactAddressをマップします。

コードでは、Person クラスは PersonAddresses のリストを保持し、Contact クラスはContactAddressesのリストを保持します。

于 2009-12-11T15:28:27.513 に答える
1

has many リレーションの場合、Any-mapping は使用できません。アドレスがさまざまな種類のオブジェクトを指すことができる場合に使用できます-人、注文、または関連のないその他のものなど。

階層をマッピングするには、次のようにします。

public class CmnAddressMap : ClassMap<CmnAddress>
{
    public CmnAddressMap()
    {
        Id(x => x.addressId);
        Map(x => x...);

        DiscriminateSubClassesOnColumn("objectType");
    }
}

public class PersonAdressMap : SubclassMap<PersonAddress>
{
    public PersonAdressMap()
    {
        DiscriminatorValue("objectType1");
    }
}

public class ContactAdressMap : SubclassMap<ContactAddress>
{
    public ContactAdressMap()
    {
        DiscriminatorValue("objectType2");
    }
}

すべてのフィールド (たとえば、CmnAdressMap 内のすべてのフィールドをマップする) を持つ抽象 CmnAddress と、PersonAddress および ContactAddress という名前の 2 つのサブクラスを用意します。

そして、その人は、HasMany にマップされるべき IList のようなコレクションを持つべきです。そして、あなたはやるべきです。

于 2009-12-11T17:26:18.377 に答える
0

住所クラス

public class Address
{
    public virtual int Id { get; set; }
    public virtual Person Person { get; set; }
    // etc.
}

人物クラス

public class Person
{
    public Person()
    {
        Addresses = new List<Address>();
    }

    public virtual int Id { get; set; }
    // etc.
    public virtual IList<Address> Addresses { get; set; }
}

アドレスマップ

public class AddressMap : ClassMap<Address>
{
    public AddressMap()
    {
        Table("CmnAddress");
        Id(x => x.Id).Column("addressId");
        // etc.
        References(x => x.Person);
    }
}

Address => Person と Address => Contact の違いを区別するには、NHibernate のポリモーフィズムを読み、列に基づいてサブクラスを区別する必要があります。

于 2009-12-11T15:21:10.123 に答える