NHibernate:将现有对象与新对象相关联?

时间:2012-06-02 20:37:01

标签: c# nhibernate nhibernate-mapping

显然,我正在搜索错误的关键字。

我在NHibernate项目中有对象VendorInvoice,如下所示:

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

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

我有一个与NH VendorRepositoryInvoiceRepository存储库的UnitOfWork样式界面......这些似乎正在发挥作用。

我可以创建一个没有汗的供应商,有点像这样:

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接口之后,但我想用最少的代码或混淆来干净地关联对象。

更新每个请求: 供应商的映射文件(删除了额外的东西):

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

}

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 

我确实尝试在映射中将一对一更改为多对一,但没有不同的结果。

第二次重新编译时,

UPDATE (并重建数据库模式)此更改有效。

2 个答案:

答案 0 :(得分:3)

我总是遇到<one-to-one>映射的麻烦。我建议转到<many-to-one unique="true">

答案 1 :(得分: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" />