早上好,
我对NHibernate很新。我想在我的新项目中使用它,但我遇到了外键引用的问题。我不确定为什么会出现这个问题。
显示的错误消息为:not-null property references a null or transient value Tec.Core.Model.Budget.oInvestmentType
这是我的表架构:
这是我的映射文件
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.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.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);
答案 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
。
更新:
还可以通过从机场,投资类型和代码