FluentNHibernate应用程序类关系

时间:2011-07-06 09:10:56

标签: nhibernate fluent-nhibernate

我正在使用FluentNHibernate和我的应用程序,我在我的应用程序中遇到了一个问题。

以下是班级结构

namespace Project.Core.Models
{
    public class Country
    {
        public virtual int CountryID { get; set; }
        public virtual string Name { get; set; }
        public virtual string ISOCountryCode { get; set; }
        public virtual string InternationalCallingCode { get; set; }
    }

    public class CustomerAddress
    {
        public virtual int CustomerAddressID { get; set; }
        public virtual string Street { get; set; }
        public virtual string TownOrCity { get; set; }
        public virtual string County { get; set; }
        public virtual string Postcode { get; set; }
        public virtual Country Country { get; set; }
        public virtual Customer Customer { get; set; }
    }

    public class Customer
    {
        public virtual int CustomerID { get; set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual bool IsActive { get; set; }

        //Customer can have more than one addresses

        public virtual IList<CustomerAddress> Addresses { get; set; }
    }
}

以下是FluentMappings

    public class CountryMap : ClassMap<Country>
    {
        public CountryMap()
        {
            Id(x => x.CountryID);
            Map(x => x.Name);
            Map(x => x.ISOCountryCode);
            Map(x => x.InternationalCallingCode);
            Table("tblCountry");
        }
    }

    public class CustomerAddressMap : ClassMap<CustomerAddress>
    {
        public CustomerAddressMap()
        {
            Id(x => x.CustomerAddressID);
            Map(x => x.Street);
            Map(x => x.TownOrCity);
            Map(x => x.County);
            Map(x => x.Postcode);
            References(x => x.Country)
                //.Not.LazyLoad()
                .Cascade.All();
            References(x => x.Customer);
            //.Not.LazyLoad();
            Table("tblCustomerAddress");
        }
    }

    public class CustomerMap : ClassMap<Customer>
    {
        public CustomerMap()
        {
            Id(x => x.CustomerID);
            Map(x => x.FirstName);
            Map(x => x.LastName);
            Map(x => x.IsActive);
            HasMany(x => x.Addresses)
                //.Not.LazyLoad()
                .Inverse()
                .Cascade.All();
            Table("tblCustomer");
        }
    }

在我的应用程序中,我已经创建了客户,但没有添加任何地址。我创建了一个用于添加/更新客户及其地址的屏幕。

  1. 屏幕上有两个用于名字和姓氏的文本框以及一个用于IsActive状态的复选框。还有一个数据网格来添加和更新客户地址。

  2. 数据网格有一个组合框列,用于其他字段的国家/地区和文本框列。

  3. 数据网格的国家/地区组合框填充了国家/地区数据库表中的国家/地区。
  4. 我的问题是向已创建的客户添加地址。 (我也不知道如何为新客户添加地址)

    在网格中键入地址详细信息并选择国家/地区后,我点击了保存按钮,期望NHibernate将数据保存到相应的表格中,并将新添加的地址链接到当前客户。

    当我检查客户对象发送NHibernate进行保存时,它已将地址添加到Addresses IList,但新添加的CustomerAddress实例的Customer属性为NULL。由于我对NHibernate / FluentNHibernate没有太多经验,我认为保存NHibernate会更新Customer for Customer地址。

    地址已保存到数据库,但未添加对客户的引用。

    但是,当我查看生成的SQL输出时,我看不到任何语句使用正确的客户ID更新新添加的客户地址。相反,它生成并更新用于更新Country的语句,这是不需要的。

    下面是NHibernate生成的SQL输出。

    NHibernate:

    INSERT INTO tblCustomerAddress (Street, TownOrCity, County, Postcode, Country_id, Customer_id) 
            VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
            @p0 = 'Street 1' [Type: String (0)], @p1 = 'Town 1' [Type: String (0)], @p2 = 'County 1' [Type: String (0)], @p3 = '123' [Type: String (0)], @p4 = 2 [Type: Int32 (0)], @p5 = NULL [Type: Int32 (0)]
    

    NHibernate:select @@IDENTITY

    NHibernate:

    UPDATE tblCountry SET Name = @p0, ISOCountryCode = @p1, InternationalCallingCode = @p2 WHERE CountryID = @p3;
            @p0 = 'United Kingdom' [Type: String (0)], @p1 = 'GBP' [Type: String (0)], @p2 = '+44' [Type: String (0)], @p3 = 2 [Type: Int32 (0)]
    

    无需更新国家/地区表格,因为这只是我用来获取正确国家/地区的参考表格。

    相反,它应该使用正确的customerID更新新添加的客户地址。我无法弄清楚我的代码中发生了什么,我不确定我是否正确指定了关系。

    如果有人可以帮我解决这个问题,那将是一个很大的帮助。

    感谢.....

    NHibernate映射一旦使用ExportTo()函数导出。

    Country.hbm.xml

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class xmlns="urn:nhibernate-mapping-2.2" name="Project.Core.Models.Country, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="tblCountry">
        <id name="CountryID" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="CountryID" />
          <generator class="identity" />
        </id>
        <property name="Name" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="Name" />
        </property>
        <property name="ISOCountryCode" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="ISOCountryCode" />
        </property>
        <property name="InternationalCallingCode" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="InternationalCallingCode" />
        </property>
      </class>
    </hibernate-mapping>
    

    Customer.hbm.xml

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class xmlns="urn:nhibernate-mapping-2.2" name="Project.Core.Models.Customer, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="tblCustomer">
        <id name="CustomerID" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="CustomerID" />
          <generator class="identity" />
        </id>
        <bag cascade="all" inverse="true" name="Addresses">
          <key>
            <column name="Customer_id" />
          </key>
          <one-to-many class="Project.Core.Models.CustomerAddress, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </bag>
        <property name="FirstName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="FirstName" />
        </property>
        <property name="LastName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="LastName" />
        </property>
        <property name="IsActive" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="IsActive" />
        </property>
      </class>
    </hibernate-mapping>
    

    CustomerAddress.hbm.xml

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class xmlns="urn:nhibernate-mapping-2.2" name="Project.Core.Models.CustomerAddress, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="tblCustomerAddress">
        <id name="CustomerAddressID" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="CustomerAddressID" />
          <generator class="identity" />
        </id>
        <property name="Street" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="Street" />
        </property>
        <property name="TownOrCity" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="TownOrCity" />
        </property>
        <property name="County" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="County" />
        </property>
        <property name="Postcode" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="Postcode" />
        </property>
        <many-to-one class="Project.Core.Models.Country, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Country">
          <column name="Country_id" />
        </many-to-one>
        <many-to-one cascade="all" class="Project.Core.Models.Customer, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Customer">
          <column name="Customer_id" />
        </many-to-one>
      </class>
    </hibernate-mapping>
    

    CustomerAddress.hbm.xml

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class xmlns="urn:nhibernate-mapping-2.2" name="Project.Core.Models.CustomerAddress, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="tblCustomerAddress">
        <id name="CustomerAddressID" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="CustomerAddressID" />
          <generator class="identity" />
        </id>
        <property name="Street" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="Street" />
        </property>
        <property name="TownOrCity" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="TownOrCity" />
        </property>
        <property name="County" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="County" />
        </property>
        <property name="Postcode" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <column name="Postcode" />
        </property>
        <many-to-one class="Project.Core.Models.Country, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Country">
          <column name="Country_id" />
        </many-to-one>
        <many-to-one cascade="all" class="Project.Core.Models.Customer, Project.Core.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Customer">
          <column name="Customer_id" />
        </many-to-one>
      </class>
    </hibernate-mapping>
    

1 个答案:

答案 0 :(得分:0)

您已在客户和客户之间建立了双向参考。 CustomerAddress对象是一件好事。问题可能是将CustomerAddress实例添加到Addresses列表的代码未设置CustomerAddress.Customer属性。以下是添加新地址时应如何显示的代码段:

  // appropriate creating/retrieving of a customer instance has happened...

  //Add a new address:
  var newAddr = new CustomerAddress();

  //Initialize property values as needed:
  newAddr.Street = "some value";
  newAddr.TownOrCity = "some other value";

  //Assign the parent instance to the References property:
  newAddr.Customer = customer;

  customer.Addresses.Add(newAddr);
  //rest of code....

如果您没有为新的CustomerAddress实例手动分配Customer引用,NHibernate将无法知道在写入数据库时​​从哪里提取Customer键。如果您正在检索Customer对象,那么NHibernate将自动连接参考分配。