【问题标题】:NHibernate - one-to-one Cascade SettingsNHibernate - 一对一的级联设置
【发布时间】:2011-06-13 15:19:32
【问题描述】:

我在 Person 类和 Employee 之间建立了一对一的关系。我希望 INSERT 从 Person 级联到 Employee。但是,这不会发生。我已经在一对一的关系元素上尝试了 cascade='all' 和 cascade='save-update' ,但它没有用。

my对象的结构如下:

public class Person
{
    public virtual Employee Employee { get; set; }
    public virtual int Age { get; set; }
    public virtual string Forename { get; set; }
    public virtual string Surname { get; set; }
    public virtual int PersonID { get; set; }
}

public class Employee
{
    public virtual int PersonID { get; set; }
    public virtual string PayRollNo { get; set; }
    public virtual int Holidays { get; set; }
    public virtual Person Person { get; set; }
}

映射文件如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Employee, Employee.DAL" table="`Employee`"  >
    <id name="PersonID" column="`PersonId`" type="int">
      <generator class="native" />
    </id>
    <property type="string" length="30" name="PayRollNo" column="`PayRollNo`" />
    <property type="int" name="Holidays" column="`Holidays`" />
    <one-to-one name="Person"  class="Person" cascade="all"/>
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="Person, Employee.DAL" table="`Person`"  >    
    <id name="PersonID" column="`PersonId`">
      <generator class="foreign">
        <param name="property" >Employee</param>
      </generator>
    </id>
    <property type="string" name="Forename" column="`Forename`" />
    <property type="string" name="Surname" column="`Surname`" />
    <property type="int" name="Age" column="`Age`" />
    <one-to-one name="Employee" class="Employee"  constrained="true"  />
  </class>
</hibernate-mapping>

初始化对象和保存对象的代码:

var employee = new Employee();

    employee.Person = new Person { Employee = employee };

    ISessionFactory sessionFactory = (new Configuration()).Configure().BuildSessionFactory();

    employee.Person.Age = 27;
    employee.Person.Forename = "N";
    employee.Person.Surname = "M";

    employee.PayRollNo = "12";
    employee.Holidays = 27;

    using (var session = sessionFactory.OpenSession())
    {
        session.Save(employee);        
    }

【问题讨论】:

    标签: nhibernate nhibernate-mapping


    【解决方案1】:

    Yads 基本上是正确的。第二个&lt;one-to-one&gt;(从员工到个人)需要constrained="true"。这样,以下代码应该可以工作:

    using (var session = sessionFactory.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        var person = new PersonDataContext();
        person.Employee = new EmployeeDataContext { Person = person };
        session.Save(person);
        tx.Commit();
    }
    

    一些额外的建议:

    • 不要不要使用lazy="false"。阅读http://ayende.com/Blog/archive/2010/08/04/nhibernate-is-lazy-just-live-with-it.aspx
    • 为您的类使用更多的 DDD 名称。您有一个表示 Person 的实体,其数据存储在 Person 表中。为什么叫它PersonDataContext
    • 您正在映射到属性,而不是字段。在您的类而不是基础字段中显示您的属性的代码。
    • 您不需要覆盖默认值。如果属性名称为PayRollNo,则默认列名称为PayRollNo。如果属性的类型是int,则默认映射类型也是int

    【讨论】:

    • 感谢您的回复。我已经应用了您的所有建议,但仍然无法正常工作,我已将示例源代码上传到 bit.ly/gNlAWr 我想知道您是否有时间快速浏览一下。非常感谢。尼玛
    • 从阅读其他问题stackoverflow.com/questions/4775430/…(您确实标记了答案)看来,您没有遵循我对代码(事务和提交)的说明
    【解决方案2】:

    将 session.Save() 方法放入事务中。或者调用 save 方法后使用 session.Flush() 方法。

           using (var trans = session.BeginTransaction())
                {
                    try
                    {
                        trans.Begin();
                        session.Save(employee);
                        trans.Commit();
                    }
                    catch
                    {
                        trans.Rollback();
                        throw;
                    }
                }
    

    Nhibernate 偶尔会存储 SQL 语句以在内存中同步日期。 session.Flush() 方法将 SQL 提交到数据库。这在 transcation.Commit() 方法上默认发生。

    有关更多信息,请参阅 Nhibernate 文档http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-flushing

    【讨论】:

      【解决方案3】:

      根据这个http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-onetoone,您在Person 映射的&lt;one-to-one&gt; 元素中缺少constrained="true"

      【讨论】:

      • 我已经采纳了您的建议,但仍然无法正常工作,我已将示例源代码上传到 bit.ly/gNlAWr 我想知道您是否有时间快速查看一下。
      • @Nima, contrained 属性在 Employee 映射上,但它应该在 Person 映射上。看起来您的外键检查也应该在 Employee 表而不是 Person 表上。
      • 谢谢亚兹。外键检查是什么意思?
      • @Nima 实际上看起来你所拥有的一切都是倒退的。是拥有外键生成的人。它的工作方式与您认为它的工作方式相反。再次重读本节,彻底nhforge.org/doc/nh/en/index.html#mapping-declaration-onetoone。而且您可能不需要 FK 约束。
      • @Yads 我的示例与您发送给我的文章中的示例有点不同。在我的示例中,Person 表中的 PersonID 是 Person 表中的 PK 和 Employee 表中的 PK 和 FK。我对吗? ;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      相关资源
      最近更新 更多