2011-01-22 2 views
0

У меня есть отношения «один к одному» между классом Person и Employee. Я ожидаю, что INSERT будет каскадом от Человека к Работнику. Однако этого не происходит. Я пробовал cascade = 'all' и cascade = 'save-update' для элемента отношения один к одному, но это не сработало.NHibernate - индивидуальные настройки каскада

Структуры моих объектов заключаются в следующем:

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);   
    } 

ответ

0

Поместите метод session.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

0

По к этому http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-onetoone Вам не хватает constrained="true" в <one-to-one> элемент в сопоставлении Person.

+0

Я применил свое предложение и до сих пор он не работает, я загрузил исходный образец код bit.ly/gNlAWr мне было интересно, если у вас есть время чтобы быстро взглянуть на нее. –

+0

@Nima, 'contrained' атрибут находится на сопоставлении Employee, но он должен находиться на сопоставлении Person. Также кажется, что ваша проверка внешнего ключа также должна быть в таблице Employee, а не в таблице Person. – Vadim

+0

Спасибо Ядс. Что вы подразумеваете под контролем внешнего ключа? –

2

Ядс по существу прав. Второй <one-to-one> (от Employee to Person) нуждается в 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.
+0

Спасибо за ваш ответ. Я применил все ваши предложения и все еще не работает, я загрузил образец исходного кода в http://bit.ly/gNlAWr. Мне было интересно, если у вас есть время, чтобы быстро взглянуть на него. Большое спасибо. Nima –

+0

Из этого другого вопроса http://stackoverflow.com/questions/4775430/nhibernate-one-to-one-mapping (для которого вы отметили ответ), похоже, что вы были ** не ** следуя моим инструкциям по коду (транзакция и фиксация) –

Смежные вопросы