hi to everybody. i'm new in nhibernate developement and got some real problems solving this error. At first i have to excuse my bad english but i have to try because after a couple of days now i'm near to give up for this or build a workaround.
i prepared a small app just to have a try how it should work. reading a lot in the documentation and on other websites i solved a lot of errors. in the end i always came to the same point an could not find a solution. if there is already a post in here i'm sorry cause i haven't found it yet.
the main problem right now is a circular reference wich produces a error when i debug my webservice. i have a typical parent-child collection should be seralized by the webservice. here the main parts in my app. the hibernate stuff is placed in an assembly and will be accessed by an web app.
Mapping documents:
Child:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="basis.DataClasses" assembly="basis">
<class name="basis.DataClasses.Child" table="t_child">
<id name="Id" column="child_id" type="Int32">
<generator class="identity" />
</id>
<property name="Name" column="child_name" type="String" not-null="true" />
<many-to-one name="TheParent" class="basis.DataClasses.Parent" column="parent_id" not-null="true" />
</class>
</hibernate-mapping>
Parent:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="basis.DataClasses" assembly="basis">
<class name="basis.DataClasses.Parent" table="t_parent">
<id name="Id" column="parent_id" type="Int32">
<generator class="identity" />
</id>
<property name="Name" column="parent_name" type="String" not-null="true" />
<bag name="TheChildren" inverse="true">
<key column="parent_id"/>
<one-to-many class="basis.DataClasses.Child"/>
</bag>
</class>
</hibernate-mapping>
Data Classes:Child:
Code:
public class Child
{
#region KEYS
private int _id;
public virtual int Id
{
get { return _id; }
set { _id = value; }
}
private int _parent_id;
public virtual int Parent_id
{
get { return _parent_id; }
set { _parent_id = value; }
}
#endregion
#region ATTRIBUTES
private string _name;
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
#endregion
#region CONSTRUCTORS
public Child() { }
#endregion
#region RELATED
private Parent theParent;
public virtual Parent TheParent
{
get { return theParent; }
set { theParent = value; }
}
#endregion
}
Parent:
Code:
[XmlInclude(typeof(Child))]
public class Parent
{
#region KEYS
private int _id;
public virtual int Id
{
get { return _id; }
set { _id = value; }
}
#endregion
#region ATTRIBUTES
private string _name;
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
#endregion
#region CONSTRUCTORS
public Parent() { }
#endregion
#region RELATED
private IList theChildren;
public virtual IList TheChildren
{
get { return theChildren; }
set { theChildren = value; }
}
#endregion
}
Session Provider:[b]
The Session is stored in HttpContext an closed by the global.asax on Request_end.
[b]controllerClass examples[b]
for each data class i produced a controllerClass which inherits a basic DAO class for insert/update and save. here an example for the parent.
Code:
public class CParent : BaseDAO
{
public Parent GetById(object id)
{
return (Parent)GetItem(typeof(Parent), id);
}
public List<Parent> GetAll()
{
List<Parent> list = new List<Parent>();
IList result = GetItems(typeof(Parent));
foreach (Parent item in result)
{
list.Add(item);
}
return list;
}
}
and the method GetItems in BaseDAO (session is not really closed)
Code:
public virtual IList GetItems(Type type)
{
IList items = null;
ISession session = SessionProvider.GetCurrentSession();
ITransaction trans = null;
try
{
trans = session.BeginTransaction();
items = session.CreateCriteria(type).List();
trans.Commit();
return items;
}
catch (Exception ex)
{
trans.Rollback();
throw new DataAccessException("Error getting items", ex);
}
finally
{
SessionProvider.CloseSession();
}
}
[b]rest of code[b]
i created another class which is called by the webservice.
Code:
public Parent[] getAllParents()
{
CChild childController = new CChild();
CParent parentController = new CParent();
List<Parent> parentList = parentController.GetAll();
Parent[] parentArray = new Parent[parentList.Count];
int i = 0;
foreach (Parent _item in parentList)
{
NHibernateUtil.Initialize(_item);
NHibernateUtil.Initialize(_item.TheChildren);
parentArray[i++] = _item;
}
return parentArray;
}
and finally the webmethod in the web app (which includes the assembly) just return an array from the method before
Code:
[WebMethod]
public Parent[] Parents()
{
AppInit _appinit = new AppInit();
return _appinit.getAllParents();
}
[b]Hibernate version: 1.2.1.4000
Dev Enviroment: Visual Studio 2005 / MSSQL Server
now here is the exception. if i have not read about all these lazy loading stuff and possibility to create bidirectional mapping files i would expect the error because it is logical in way. i really have tried a lot of things and now i'm at the point that i have missed something.
Full stack trace of any exception that occurs:
System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: A circular reference was detected while serializing an object of type basis.DataClasses.Parent.
at System.Xml.Serialization.XmlSerializationWriter.WriteStartElement(String name, String ns, Object o, Boolean writePrefixed, XmlSerializerNamespaces xmlns)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write3_Parent(String n, String ns, Parent o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write2_Child(String n, String ns, Child o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write3_Parent(String n, String ns, Parent o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write4_ArrayOfParent(Object o)
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfParentSerializer.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o)
at System.Web.Services.Protocols.XmlReturnWriter.Write(HttpResponse response, Stream outputStream, Object returnValue)
at System.Web.Services.Protocols.HttpServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream)
at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues)
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
i hope this is enough to get the point. so what is my mistake. did i understood the whole thing in a wrong way or is it just a small mistake in the code files. please do inform me if a created the architecture in right way.
thank for answers even if they should be: read the manual again.