如何使用NHibernate(Fluent)映射此旧表?

时间:2009-12-11 14:59:03

标签: nhibernate fluent-nhibernate mapping hierarchy legacy

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”)字段匹配。

我后来还要创建一个Contact类,它还包含一个地址列表,其中objectType列包含“CmnContact”。

我很难搞清楚我是否应该使用Any映射或每个类的class-hierarchy对子列进行区分?或者,如果其中任何一个甚至满足我的需求。

有人能告诉我如何映射这个地址类吗? Fluent配置会更好。

添加信息:

以下类和映射几乎可以工作,但是无论objectType字段的值如何,Addresses列表都会返回CmnAddress表中具有匹配objectId的所有行。我想我可以在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");
  }
}

3 个答案:

答案 0 :(得分:1)

抱歉,我不熟悉流畅的映射,但是,一种方法是:

  • 创建地址抽象类,其属性对应于表格中的所有列,但 objectType
  • 除外
  • 创建 PersonAddress 类,扩展地址
  • 创建 ContactAddress 类,其中包含地址

  • 以正常方式将 CmnAddress 的所有列映射到地址类的属性,但声明的 objectType 除外作为鉴别列

  • 人物地址映射为地址的子类,并带有鉴别器值“CmnPerson”
  • ContactAddress 映射为地址的子类,并使用“CmnContact”
  • 进行鉴别器值

在代码中,您的Person类将包含 PersonAddresses 列表,而您的Contact类将包含 ContactAddresses

列表

答案 1 :(得分:1)

当它有很多关系时,你不能使用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");
    }
}

具有包含所有字段的抽象CmnAddress(例如,映射CmnAdressMap中的所有字段)和两个名为PersonAddress和ContactAddress的子类。

然后这个人应该拥有像IList这样的集合,它应该与HasMany映射。你应该完成。

答案 2 :(得分: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; }
}

AddressMap

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

分隔地址=&gt;之间的差异人和地址=&gt;联系,您需要阅读NHibernate的多态性并根据列区分子类。