2012-06-02 3 views
4

Я искал неправильные ключевые слова.NHibernate: связать существующий объект с новым объектом?

У меня есть объекты на VendorInvoice и в проекте NHibernate, как так:

public class Vendor 
{ 
    public string theName { get; set; } 
} 

public class Invoice 
{ 
    public Vendor theVendor { get; set; } 
    public decimal Amount { get; set; } 
} 

У меня есть интерфейс в стиле UnitOfWork с NH VendorRepository и InvoiceRepository хранилищ ... это, кажется, работает.

Я могу создать вендор не пот, Сорта, как это:

public void CreateVendor(string name) 
{ 
    using (var u = new UnitOfWork()) 
    { 
     var v = new Vendor(); 
     v.theName = name; 
     u.Vendors.Add(v); 
     u.Save(); 
    } 
} 

Invoice Создание объекта, однако, требует ссылки на Vendor. Я думал, что это будет так же просто, как:

public void CreateInvoice(decimal theAmount, string vendorName) 
{ 
    using (var u = new UnitOfWork()) 
    { 
     var i = new Invoice(); 
     i.Amount = theAmount; 
     var v = u.Vendors.GetByName(vendorName); 
     i.theVendor = v; 
     u.Invoices.Add(i); 
     u.Save(); 
    } 
} 

Однако, похоже, это не так. Нужно ли мне делать какой-то особый вуду в NHibernate? Я бы предпочел сохранить NHibernate за интерфейсом UnitOfWork, но я хотел бы чисто ассоциировать объекты с минимальным кодом или путаницей.

UPDATE По желанию: Mapping файл (дополнительный материал удален) для поставщика:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        assembly="DataModel" 
        namespace="DataModel"> 
    <class name="Vendor" table="Vendors"> 
     <id name="APVendorId"> 
      <generator class="guid" /> 
     </id> 
     <property name="theName" index="ixVendorName" length="100" not-null="true" column="VendorName" /> 
    </class> 
</hibernate-mapping> 

и фактуре:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        assembly="C3.DataModel" 
        namespace="C3.DataModel"> 
    <class name="Invoice" table="Invoices"> 
     <id name="InvoiceId"> 
      <generator class="guid" /> 
     </id> 
     <one-to-one name="Vendor" class="Vendor" constrained="true" cascade="none" fetch="join" /> 
     <property name="theAmount" column="InvoiceAmount" not-null="true" /> 
    </class> 
</hibernate-mapping> 

код хранилище напоминает это:

///<summary> 
///Auto-generated NHibernate repository for the domain POCO object <strong>APInvoice</strong> 
///</summary> 
public partial class NHInvoiceRepository : IInvoiceRepository 
{ 
    internal ISession _Session; 
    internal ITransaction _Transaction; 
    private bool _IndependentSession; 

    ///<summary> 
    ///Adds a Invoice object to the NHibernate repository. 
    ///</summary> 
    public void Add(Invoice invoice) 
    { 
     _Session.Save(invoice); 
    } 

    ///<summary> 
    ///Instantiates the repository in standalone (no associated UnitOfWork) mode. This should usually be avoided. 
    ///</summary> 
    internal NHInvoiceRepository() 
    { 
     _Session = NHibernateHelper.OpenSession(); 
     _Transaction = _Session.BeginTransaction(); 
     _IndependentSession = true; 
    } 

    ///<summary> 
    ///Instantiates the repository as a part of a UnitOfWork pattern. 
    ///</summary> 
    public NHInvoiceRepository(ISession session, ITransaction transaction) 
    { 
     _Session = session; 
     _Transaction = transaction; 
     _IndependentSession = false; 
    } 

    ///<summary> 
    ///Instantiates the repository as a part of a UnitOfWork pattern. 
    ///</summary> 
    public NHInvoiceRepository(ISession session) 
    { 
     _Session = session; 
     _Transaction = _Session.BeginTransaction(); 
     _IndependentSession = false; 
    } 

    ///<summary> 
    ///Implements the IDisposable interface. 
    ///</summary> 
    public void Dispose() 
    { 
     _Transaction.Dispose(); 
     _Session.Dispose(); 
     return; 
    } 

    ///<summary> 
    ///Commits the changes in the repository in standalone (no associated UnitOfWork) mode. 
    ///</summary> 
    public void Save() 
    { 
     if (_IndependentSession) 
     { 
      _Transaction.Commit(); 
      _Transaction = _Session.BeginTransaction(); 
     } 
    } 

} 

The UnitOfWork Код выглядит следующим образом:

///<summary> 
///UnitOfWork Interface. The primary data interface between the data model and the persistence layer. 
///</summary> 
public partial class NHUnitOfWork : IUnitOfWork 
{ 
    private ISession _Session; 
    private ITransaction _Transaction; 
    public IVendorRepository Vendors { get; private set; } 
    public IInvoiceRepository Invoices { get; private set; } 

    public void Save() 
    { 
     Vendors.Save(); 
     Invoices.Save(); 
     _Transaction.Commit(); 
    } 

    public void Dispose() 
    { 
     Vendors.Dispose(); 
     Invoices.Dispose(); 
     _Transaction.Dispose(); 
     _Session.Dispose(); 
    } 

    public NHUnitOfWork() 
    { 
     _Session = NHibernateHelper.OpenSession(); 
     _Transaction = _Session.BeginTransaction(); 
     Vendors = new NHVendorRepository(_Session); 
     Invoices = new NHInvoiceRepository(_Session); 
    } 
} 

Сообщение об ошибке я получаю:

NHibernate.PropertyValueException: not-null property references a null or transient value 

Я попытаться изменить один к одному на многие-к-одному в соответствиях, без различных результатов ,

ОБНОВЛЕНИЕ на втором этапе перекомпиляции (и восстановление схемы db) это изменение сработало.

+1

Почему бы не метод требует экземпляр поставщика вместо этого? Это имело бы смысл для меня: public void CreateInvoice (decimal theAmount, поставщик поставщика); ' –

+0

Я думаю, что проблема связана с вашими сопоставлениями, можете ли вы разместить сопоставления ваших двух классов? – Jupaol

+0

Он должен хорошо работать с NHibernate. Как работают 'Vendors.Add()' и 'UnitOfWork.Save()'? – ivowiblo

ответ

3

У меня всегда были проблемы с <one-to-one> сопоставлениями. Я предлагаю, чтобы перейти к <many-to-one unique="true">

+0

Я думаю (думаю), что NHibernate ожидает, что оба объекта будут иметь один и тот же идентификатор, если они связаны друг с другом. Я думаю, не был определен для 1 до 0..1 по мере необходимости. – ivowiblo

+0

Ум ... переходите к чему? –

+0

Основываясь на вашей ошибке, я уверен, что это проблема. Проверьте эту ссылку: http://ayende.com/blog/3960/nhibernate-mapping-one-to-one – ivowiblo

2

Я думаю, что проблема с этой линией

<one-to-one name="Vendor" class="Vendor" constrained="true" cascade="none" fetch="join" /> 

Попробуйте заменить его

<many-to-one name="Vendor" unique="true" cascade="all" fetch="join" /> 
+0

легко с каскадом = "все". Но я думаю, что «сохранить-обновить» будет достаточно – ivowiblo

+0

Mmmhhh теперь, когда я думаю, что это лучше, я не считаю, что это каскадная проблема. Итак, каскад = «все» не должно быть – ivowiblo

+0

Неужели у? таким образом, большинство картографических генераторов отображают такое отношение. – Jupaol

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