Nhibernate not-null属性引用空值或瞬态值Tec.Core.Model.Budget.oInvestmentCode

时间:2014-02-25 02:36:59

标签: c# xml nhibernate

早上好,

我对NHibernate很新。我想在我的新项目中使用它,但我遇到了外键引用的问题。我不确定为什么会出现这个问题。

显示的错误消息为:not-null property references a null or transient value Tec.Core.Model.Budget.oInvestmentType

这是我的表架构:

enter image description here

这是我的映射文件

机场

Airport.hbm.xml

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">   
<class name="Tec.Core.Model.Airport, Tec.Core" table="tblAirport" lazy="false">
    <id name="ID" column="AirportID" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="AirportCode" column="AirportCode" />
    <property name="AirportFullName" column="AirportFullName" />

    <bag name="Budgets" table="tblBudget" inverse="true" cascade="save-update">
      <key column="AirportID" />
      <one-to-many class="Tec.Core.Model.Budget, Tec.Core" />
    </bag>
</class> 
</hibernate-mapping>

Airports.cs

public class Airport:Entity<int> 
{
    private string _airportCode="";
    private string _airportFullName="";
    private IList<Budget> _airportBudgets = new List<Budget>();

    private Airport() { }
    public Airport(string AirportCode, string AirportFullName) {
        this._airportCode = AirportCode;
        this._airportFullName = AirportFullName; 
    }                
     public  string AirportCode  {
        get { return _airportCode; }
        set { _airportCode = value; }
    }
    public  string AirportFullName {
        get { return _airportFullName; }
        set { _airportFullName = value; }
    }
    public IList<Budget> Budgets {
        get { return new List<Budget>(_airportBudgets).AsReadOnly(); }
        protected set { _airportBudgets = value; }
    }
    public void AddBudget(Budget air_budget){
        if (air_budget != null && !_airportBudgets.Contains(air_budget)){
            air_budget.oAirport = this; 
            _airportBudgets.Add(air_budget);
        }
    }

    public override int GetHashCode(){
        return (GetType().FullName + "|" + _airportCode.GetHashCode()).GetHashCode();
    }

}

InvestmentCode

InvestmentCode.hbm.xml

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">   
<class name="Tec.Core.Model.InvestmentCode, Tec.Core" table="tblInvestmentCode" lazy="false">
    <id name="ID" column="InvestmentCodeID" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="InvCode" column="InvestmentCode" />
    <property name="InvCodeNote" column="InvestmentCodeNote" />

    <bag name="Budgets" table="tblBudget" inverse="true" cascade="save-update">
      <key column="InvestmentCodeID" />
      <one-to-many class="Tec.Core.Model.Budget, Tec.Core" />
    </bag>
  </class> 
</hibernate-mapping>

InvestmentCode.cs

  

public class InvestmentCode:Entity       {

    private string _investmentCode="";
    private string _investmentCodeNote="";
    private IList<Budget> _lstinvestmentCodeBudgets = new List<Budget>();

    private InvestmentCode() { }
    public InvestmentCode(string investmentCode, string InvestmentCodeNote) {
        this._investmentCode = investmentCode;
        this._investmentCodeNote = InvestmentCodeNote ; 
    }      
    public string InvCode {
        get { return _investmentCode ; }
        set { _investmentCode  = value; }
    }
    public string InvCodeNote {
        get { return _investmentCodeNote ; }
        set { _investmentCodeNote  = value; }
    }
    public IList<Budget> Budgets {
        get { return new List<Budget>(_lstinvestmentCodeBudgets).AsReadOnly(); }
        protected set { _lstinvestmentCodeBudgets = value; }
    }
    public void AddBudget(Budget investment_code_budget) {
        if (investment_code_budget != null && !_lstinvestmentCodeBudgets.Contains(investment_code_budget)){
            investment_code_budget.oInvestmentCode = this; 
            _lstinvestmentCodeBudgets.Add(investment_code_budget);
        }
    }        
    public override int GetHashCode(){
        return (GetType().FullName +"|"+ _investmentCode.GetHashCode()).GetHashCode();
    }
}

InvestmentType

InvestmentType.hbm.xml

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">   
<class name="Tec.Core.Model.InvestmentType, Tec.Core" table="tblInvestmentType" lazy="false">
    <id name="ID" column="InvestmentTypeID" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="InvestmentTypeNote" column="InvestmentTypeNote" />    

    <bag name="Budgets" table="tblBudget" inverse="true"  cascade="save-update">
      <key column="InvestmentTypeID" />
      <one-to-many class="Tec.Core.Model.Budget, Tec.Core" />
    </bag>
</class> 
</hibernate-mapping>

InvestmentType.cs

  

公共类投资类型:实体{

    private string _investmentTypeNote="";
    private IList<Budget> _lstInvestmentTypeBudgets = new List<Budget>();

    private InvestmentType() { }

    public InvestmentType(string InvestmentTypeNote){            
        this._investmentTypeNote = InvestmentTypeNote ; 
    }
    public string InvestmentTypeNote {
        get { return _investmentTypeNote ; }
        set { _investmentTypeNote  = value; }
    }
    public IList<Budget> Budgets {
        get { return new List<Budget>(_lstInvestmentTypeBudgets).AsReadOnly(); }
        protected set { _lstInvestmentTypeBudgets = value; }
    }
    public void AddBudget(Budget investment_type_budget)  {
        if (investment_type_budget != null && !_lstInvestmentTypeBudgets.Contains(investment_type_budget)){
            investment_type_budget.oInvestmentType = this; 
            _lstInvestmentTypeBudgets.Add(investment_type_budget);
        }
    }
    public override int GetHashCode(){
        return (GetType().FullName + "|"+ _investmentTypeNote.GetHashCode()).GetHashCode();
    }
}

预算

Budget.hbm.xml

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">   
<class name="Tec.Core.Model.Budget, Tec.Core" table="tblBudget" lazy="false">
    <id name="ID" column="BudgetID" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="BudgetAmount" column="BudgetAmount" />
    <property name="BudgetYear" column="BudgetYear" />

    <many-to-one name="oAirport" column="AirportID"
      class="Tec.Core.Model.Airport, Tec.Core" not-null="true" />
    <many-to-one name="oInvestmentCode" column="InvestmentCodeID"
      class="Tec.Core.Model.InvestmentCode, Tec.Core" not-null="true" />
    <many-to-one name="oInvestmentType" column="InvestmentTypeID"
      class="Tec.Core.Model.InvestmentType, Tec.Core" not-null="true" />  
</class> 
</hibernate-mapping>

Budget.cs

   public class Budget:Entity<long> 
   {
    private float _budgetAmount;
    private int _budgetYear;
    private InvestmentType _investmentType;
    private InvestmentCode _investmentCode;
    private Airport _airport;

    public Budget() { }
    public float BudgetAmount {
        get{return _budgetAmount; }
        set{_budgetAmount = value;}
    }        
    public int BudgetYear {
        get{return _budgetYear; }
        set{_budgetYear = value;}
    }        
    public Airport oAirport{
        get{return _airport; }
        set{_airport = value;}
    }        
    public InvestmentType oInvestmentType{
        get{return _investmentType; }
        set{_investmentType  = value;}
    }        
    public InvestmentCode oInvestmentCode {
        get{return _investmentCode ; }
        set{_investmentCode = value;}
    }
    public override int GetHashCode(){
        return (GetType().FullName + "|" + _airport.GetHashCode() +"|"+ _investmentCode.GetHashCode()+"|"+ _investmentType.GetHashCode()).GetHashCode();
    }

}

在我的Default.asp.cs

我有以下代码:

        Airport objA = new Airport("NA", "New Airport")
        InvestmentCode objIC = new InvestmentCode("1000", "ABCD");
        InvestmentType objIT = new InvestmentType("Capex");

        Budget objBg = new Budget();
        objBg.oAirport = objA;
        objBg.oInvestmentCode = objIC;
        objBg.oInvestmentType = objIT;
        objBg.BudgetAmount = 10000;
        objBg.BudgetYear = 2014;

        objA.AddBudget(objBg);
        AirportDao.SaveOrUpdate(objA);

        objIC.AddBudget(objBg);
        daoFactory.GetInvestmentCodeDao().Save(objIC);  //Error occur here not-null property references a null or transient value Tec.Core.Model.Budget.oInvestmentType


        objIT.AddBudget(objBg);            
        daoFactory.GetInvestmentTypeDao().Save(objIT);     

2 个答案:

答案 0 :(得分:0)

我不会赌我的生活..但我会说你的问题在这里:

public IList<Budget> Budgets {
    get { return new List<Budget>(_lstinvestmentCodeBudgets).AsReadOnly(); }
    protected set { _lstinvestmentCodeBudgets = value; }
}

此代码按此顺序调用:

objA.AddBudget(objBg);
AirportDao.SaveOrUpdate(objA);

objA已保留.. objBg也会级联并保留。这意味着NHiberante会跟踪objBg的引用。

然后你称之为:

objIC.AddBudget(objBg);

将预算按预期添加到列表中。我们将此列表称为“列表A”。

然后你去打电话保存:

daoFactory.GetInvestmentCodeDao().Save(objIC);

当NHibernate开始从您的实体读取值时......它会出现在您的getter中:

get { return new List<Budget>(_lstInvestmentTypeBudgets).AsReadOnly(); }

您已将财产包裹在新列表中。所以现在,这是“List B”..而不是NHIBnate所期望的“List A”。 “List B”并没有被持久化。所以NHibernate说“等等......你试图坚持我不会在更新中跟踪的东西”。

尝试将您的getter更改为:

get { return _lstInvestmentTypeBudgets; }

..看看是否有效。它应该..因为你正在返回相同的实例。

答案 1 :(得分:0)

映射需要稍微修正。预算案是一个实体,其组成参考机场,投资和投资代码。预算不能像子类一样添加到其他类,因为这里没有“一对多”关系。因此,请从三个类中删除addBudget方法,并将以下方法添加到Budget类 - &gt; AddAirport, AddInvestmentCode, AddInvestmentType。 更新: 还可以通过从机场,投资类型和代码

中删除指向预算类别的行李来相应地更正映射
相关问题