I have an "OrderID" property on a child object that is an integer and is >= 1 and may or may not have sequential values, so cannot use list mapping. I am using the OrderID column as the index of the parent's map to reference the child as one-to-many.
I can add an OrderID property on the child so that I can change it, and that persists fine, but while the session is open, the hashtable never reflects the key changes. Is there a way to alter the keys of a map/hashtable and have it reflected correctly?
Parent HBM:
Code:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping schema="dbo" xmlns="urn:nhibernate-mapping-2.0">
<meta attribute="filename">Parent.hbm.xml</meta>
<class name="Test.Parent, ConsoleApplication1" table="parent">
<id name="Id" access="nosetter.camelcase" column="id" type="Int32" unsaved-value="0">
<meta attribute="codeAccess">getter</meta>
<meta attribute="fill-factor">50</meta>
<meta attribute="clustered">true</meta>
<generator class="identity" />
</id>
<map name="Children" access="property" table="parent" cascade="all-delete-orphan" inverse="true">
<meta attribute="codeAccess">both</meta>
<key column="parent_id" foreign-key="fk_child_parent" />
<index column="OrderID" type="Int32" />
<one-to-many class="Test.Child, ConsoleApplication1" />
</map>
<property name="Name" access="property" type="AnsiString" column="name" length="50" not-null="true">
<meta attribute="codeAccess">both</meta>
</property>
</class>
</hibernate-mapping>
Child HBM:
Code:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping schema="dbo" xmlns="urn:nhibernate-mapping-2.0">
<meta attribute="filename">Child.hbm.xml</meta>
<class name="Test.Child, ConsoleApplication1" table="child">
<id name="Id" access="nosetter.camelcase" column="id" type="Int32" unsaved-value="0">
<meta attribute="codeAccess">getter</meta>
<meta attribute="fill-factor">50</meta>
<meta attribute="clustered">true</meta>
<generator class="identity" />
</id>
<property name="Name" access="property" type="AnsiString" column="name" length="50" not-null="true">
<meta attribute="codeAccess">both</meta>
</property>
<many-to-one name="Parent" access="property" class="Test.Parent, ConsoleApplication1" column="parent_id" not-null="true" cascade="none">
<meta attribute="codeAccess">both</meta>
</many-to-one>
<property name="OrderID" access="property" type="Int32" column="orderID">
<meta attribute="codeAccess">both</meta>
</property>
</class>
</hibernate-mapping>
Parent C#:
Code:
// This file has been generated from the persistence tool.
using System;
using System.Collections;
using MortgageCadence.Persist;
using ThreeT.Utility;
using ThreeT.Utility.Primitives;
using ThreeT.Utility.WinUI;
namespace Test
{
[Serializable]
public class Parent
: PersistedType
{
#region fields
private static readonly int UnsavedValue = 0;
private int id = 0;
private IDictionary children;
private string name;
#endregion fields
#region constructors
#endregion constructors
#region Change tracking properties
/// <summary>
/// Check if this instance is new using the unsaved value of the ID
/// </summary>
public override bool IsNew
{
get
{
return (this.Id == Parent.UnsavedValue);
}
}
#endregion Change tracking properties
#region properties
public virtual int Id
{
get { return this.id; }
}
public virtual string Name
{
get { return this.name; }
set
{
// Make sure this isn't the same value
if (this.name == value) return;
this.name = value;
this.OnPropertyChange("Name");
}
}
#endregion properties
#region related properties
#endregion related properties
#region collections
public virtual IDictionary Children
{
get { return this.children; }
set
{
// Make sure this isn't the same value
if (this.children == value) return;
this.children = value;
this.OnPropertyChange("Children");
}
}
#endregion collections
#region property specific functions
#endregion property specific functions
#region functions
/// <summary>
/// See <see cref="object.Equals(object)" />
/// </summary>
public override bool Equals(object value)
{
Parent castValue = value as Parent;
// Make sure the cast worked
if (castValue == null) return false;
// See if the value passed in is the same as the current value
// (this allows for '==' overloads in the base class)
if (castValue == this) return true;
// See if this class is unsaved, if so, do not compare IDs
if (this.Id == Parent.UnsavedValue)
return false;
// This class has a non-unsaved value for the ID. Compare this ID with the ID of
// the passed in value's ID
return (this.id == castValue.id);
}
/// <summary>
/// See <see cref="object.GetHashCode()" />
/// </summary>
public override int GetHashCode()
{
// See if this class is unsaved, if so, use the default get hash code method
if (this.Id == Parent.UnsavedValue)
return base.GetHashCode();
return id.GetHashCode();
}
#endregion functions
}
}
Child C#:
Code:
// This file has been generated from the persistence tool.
using System;
using System.Collections;
using MortgageCadence.Persist;
using ThreeT.Utility;
using ThreeT.Utility.Primitives;
using ThreeT.Utility.WinUI;
namespace Test
{
[Serializable]
public class Child
: PersistedType
{
#region fields
private static readonly int UnsavedValue = 0;
private int id = 0;
private Parent parent;
private string name;
private int orderID;
#endregion fields
#region constructors
#endregion constructors
#region Change tracking properties
/// <summary>
/// Check if this instance is new using the unsaved value of the ID
/// </summary>
public override bool IsNew
{
get
{
return (this.Id == Child.UnsavedValue);
}
}
#endregion Change tracking properties
#region properties
public virtual int Id
{
get { return this.id; }
}
public virtual string Name
{
get { return this.name; }
set
{
// Make sure this isn't the same value
if (this.name == value) return;
this.name = value;
this.OnPropertyChange("Name");
}
}
public virtual int OrderID
{
get { return this.orderID; }
set
{
// Make sure this isn't the same value
if (this.orderID == value) return;
this.orderID = value;
this.OnPropertyChange("OrderID");
}
}
#endregion properties
#region related properties
public virtual Parent Parent
{
get { return this.parent; }
set
{
// Make sure this isn't the same value
if (this.parent == value) return;
this.parent = value;
this.OnPropertyChange("Parent");
}
}
#endregion related properties
#region collections
#endregion collections
#region property specific functions
#endregion property specific functions
#region functions
/// <summary>
/// See <see cref="object.Equals(object)" />
/// </summary>
public override bool Equals(object value)
{
Child castValue = value as Child;
// Make sure the cast worked
if (castValue == null) return false;
// See if the value passed in is the same as the current value
// (this allows for '==' overloads in the base class)
if (castValue == this) return true;
// See if this class is unsaved, if so, do not compare IDs
if (this.Id == Child.UnsavedValue)
return false;
// This class has a non-unsaved value for the ID. Compare this ID with the ID of
// the passed in value's ID
return (this.id == castValue.id);
}
/// <summary>
/// See <see cref="object.GetHashCode()" />
/// </summary>
public override int GetHashCode()
{
// See if this class is unsaved, if so, use the default get hash code method
if (this.Id == Child.UnsavedValue)
return base.GetHashCode();
return id.GetHashCode();
}
#endregion functions
}
}
Test code:
Code:
using System;
using System.Diagnostics;
using NHibernate;
using MortgageCadence.Loan;
using Test;
namespace MortgageCadence.Persist
{
/// <summary>
///
/// </summary>
public class MainClass
{
public static int Main(string[] args)
{
try
{
using (ISession session = HibernateUtil.CreateSession())
using (ITransaction tx = session.BeginTransaction())
{
Parent p = (Parent)session.Get(typeof(Parent), 2);
Child c = (Child)p.Children[2];
c.OrderID = 3;
tx.Commit();
p = (Parent)session.Get(typeof(Parent), 2);
foreach (int i in p.Children.Keys)
Trace.WriteLine("OrderID: " + i);
return 0;
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex);
return 5;
}
}
}
}