I'm trying to map a complex object where it both hierarchical and old versions need to be stored. Each object has a Parent property a Children property. Old data remains in the database with an inactive flag set. Each version has a date and multiple versions can be active at a time with the most recent active version with a valid date being the current version.
I think I have a solution that will work. I just wanted to post this to see if anyone else can see any gotchas or has a better solution.
The solution I have is to use two tables (one with non-changing data and one for the versions) with a view that selects the current versions only.
The tables look something like this:
Code:
Widgets
Id
other non-versioned fields
WidgetVersions
VersionId
VersionNumber
WidgetId
ParentId <--- id of a Widget
SortOrder
Active
VersionDate
StartDate
EndDate
other versioned fields
CurrentWidgets (view)
Id
other non-versioned fields
CurrentVersionId
CurrentVersionParentId
CurrentVersionSortOrder
The classes are similar to the tables:
Code:
public class Widget
{
int Id { get; set; }
ReadOnlyCollection<Widget> Children { get; }
WidgetVersion CurrentVersion { get; }
IList<WidgetVersion> Versions { get; }
}
public class WidgetVersion
{
int VersionId { get; set; }
int VersionNumber { get; set; }
bool Active { get; set; }
DateTime VersionDate { get; set; }
DateTime StartDate { get; set; }
DateTime? EndDate { get; set; }
string OtherData { get; set; }
WidgetVersion NewVersion()
{
// copy all fields
// set new VersionDate
// increment VersionNumber
// return copy
}
}
The mapping files are pretty straightforward, the only interesting bit is CurrentVersionId, CurrentVersionParentId, and CurrentVersionSortOrder have update="false" insert="false". Children and Versions properties are not currently lazy loading, but probably will be.
Client code for editing a new version looks something like this:
Code:
WidgetVersion newVersion = widget.CurrentVersion.NewVersion()
newVersion.OtherData = whatever
foreach (WidgetVersion v in widget.Versions)
v.Active = false;
widget.Versions.Add(newVersion);
The only downside I can see is that I am not able to add or remove from the Children list directly. Instead I have to set a version's parent, then refresh the parent object from the database.
I'm basing a lot of my ideas off this post:
http://forum.hibernate.org/viewtopic.ph ... 82#2250234. I'm using SQL Server 2005, .net 3.5 and NHibernate 1.2.1GA
Is this a good way to handle this with NHibernate? Are there any common solutions for this kind of situation? Does anyone out there have experience with a similar problem?
Sorry if this got a bit long, I tried to keep it short and still cover the problem.
Thanks,
David