代码之家  ›  专栏  ›  技术社区  ›  quentin-starin

如何用nhibernate(fluent)映射这个遗留表?

  •  0
  • quentin-starin  · 技术社区  · 16 年前

    新的氨气。在如何映射这个遗留的表上绕着我的头有困难。

    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,
    )
    

    还有一个“cmnperson”表,我已经映射到了一个person类。我需要Person类包含地址列表,其中objectType列包含“cmnPerson”,objectid字段与我的person.id(“cmnPerson.person id”)字段匹配。

    稍后,我还必须创建一个contact类,该类还包含objectType列中包含“cmcontact”的地址列表。

    我很难弄清楚是否应该在每个表中使用任何映射或类层次结构,并区分子列?或者如果其中任何一个都能满足我的需要。

    有人能告诉我如何映射这个地址类吗?最好是流畅的配置。

    添加的信息:

    下面的类和映射几乎可以工作,但是地址列表使用匹配的objectid返回cmnaddress表中的所有行,而不管objecttype字段的值如何。我想我可以在hasmany映射中为person.addresses使用applyfilter,但这似乎不是“正确”的方式。

    更多添加信息: 我可以通过在调用distingSubclassesOnColumn(…)后链接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 回复  |  直到 16 年前
        1
  •  1
  •   asgerhallas    16 年前

    当任何映射具有多个关系时,都不能使用它。当一个地址可以指向不同类型的对象时,可以使用它,比如一个人、一个订单或其他与之无关的东西。

    要映射层次结构,可以这样做:

    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中的所有字段)和两个名为personalddress和contactaddress的子类。

    然后这个人应该有一个像ilist这样的集合,它应该映射到hasmany。你应该完成。

        2
  •  1
  •   alasdairg    16 年前

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

    • 创建 地址 抽象类,其属性与表中除 对象类型
    • 创建一个 人物地址 扩展的类 地址
    • 创建一个 接触地址 扩展的类 地址

    • 映射的所有列 CMNATHOLD 到的属性 地址 以正常方式上课,除了 对象类型 声明为鉴别器列

    • 地图 人物地址 作为 地址 带有鉴别器值“cmnperson”
    • 地图 联系人地址 作为 地址 带有“cmcontact”的鉴别器值

    在代码中,您的Person类将包含 人物称呼 你的联系班会有一份 联系人地址

        3
  •  0
  •   Jarrett Meyer    16 年前

    地址类

    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的多态性并根据列区分子类。