Hi, I am assuming it is possible to persist objects with circular references as neither google nor the manual seem to say this is impossible (or perhaps I have been using the wrong search terms). If this is the case I believe it stems from a fairly fundamental misunderstanding of how to persist a simple single object reference and have this cascaded upon save.
The best way to explain is in the example below. I basically create a class of the form:
Code:
public class A
{
public virtual int Id { get; set; }
public virtual A Next { get; set; }
}
and then create 2 objects of type A called a1,a2
I set it up so that they point to one another, e.g.
a1.Next = a2;
a2.Next = a1;
I would then like to create mappings so that when I save one, the other is automatically saved via cascade in such a manner that their Next members are preserved. I have not been able to do this. Could somebody please give me an example of a mapping that can do this?
So far I have tried creating a hbm.xml which uses a many-to-one mapping. This does not work as a1.Next is not saved in the database. (Out of desperation I tried a one-to-one mapping but this results in an even more nonsensical setup, creating a table with nothing but an Id column)
example below:
Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using FluentNHibernate.Cfg;
using FluentNHibernate.Mapping;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
namespace hibernate.experiment
{
[TestFixture]
public class CircularDemo
{
[Test]
public void CircularTest()
{
var file = "circulardemo.db";
if (File.Exists(file))
File.Delete(file);
Configuration c = new Configuration();
c.Properties["dialect"] = "NHibernate.Dialect.SQLiteDialect";
c.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
c.Properties["connection.driver_class"] = "NHibernate.Driver.SQLite20Driver";
c.Properties["connection.connection_string"] = "Data Source=" + file + ";Version=3;";
c.AddFile("hibernate.experiment.CircularDemo+A.hbm.xml");
new SchemaExport(c).Create(true, true);
var sFactory = c.BuildSessionFactory();
using (var s = sFactory.OpenSession())
{
A a1 = new A();
A a2 = new A();
a1.Next = a2;
a2.Next = a1;
Assert.NotNull(a1.Next);
Assert.NotNull(a2.Next);
s.Save(a1);
}
using (var s = sFactory.OpenSession())
{
foreach (var a in s.CreateCriteria(typeof(A)).List<A>())
Assert.NotNull(a.Next);
}
}
public class A
{
public virtual int Id { get; set; }
public virtual A Next { get; set; }
}
}
}
hibernate.experiment.CircularDemo+A.hbm.xml file below:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="">
<class name="hibernate.experiment.CircularDemo+A, hibernate.experiment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`A`" xmlns="urn:nhibernate-mapping-2.2">
<id name="Id" type="Int32" column="Id">
<generator class="identity" />
</id>
<many-to-one cascade="all" name="Next" column="Next_id" />
</class>
</hibernate-mapping>
If someone could explain what I am doing wrong I would be grateful.