I am new to NHibernate and have found it extremely interesting. I have been trying to persist objects to a mapping table (the table that breaks a many to many relations in the relational database design) but not been able to do so so far. I am able to retrieve data from the mapping table using my current hibernate-mapping, though.
Here is what my database looks like:
Groups (groupId, groupName) Reports (reportID, reportName) GroupReports(groupId, reportId)
Very typical and simple relations in terms of data modeling.
I know this question has been asked many times and I have read lots of them. Believe me, I really did.
Here is my mapping for the Group entity class:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataTransfer" namespace="DataTransfer">
<class name="DataTransfer.Group, DataTransfer" table="GROUPS">
<id name="GroupId">
<column name="groupId" sql-type="int" not-null="true"/>
<generator class="native"/>
</id>
<property name="GroupName" column="groupName" type ="string" length="150" not-null="true"/>
<bag name="Reports" cascade="none" inverse="true">
<key column="groupId"/>
<many-to-many column="reportId" class="DataTransfer.Report, DataTransfer"/>
</bag>
</class>
</hibernate-mapping>
And my mapping for the Report entity class likes below:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataTransfer" namespace="DataTransfer">
<class name="DataTransfer.Report, DataTransfer" table="REPORTS" >
<id name="ReportId" column="reportId" type="int" unsaved-value="0">
<generator class="native"/>
</id>
<property name = "ReportName" column="reportName" type="string" length="250" not-null="true"/>
<bag name="MappedGroups" table="GroupReports" cascade="all" inverse="false" lazy="true">
<key column="reportId"/>
<many-to-many class="DataTransfer.Group, DataTransfer" column="groupId" />
</bag>
</class>
</hibernate-mapping>
According to what I have read, these mappings should allow me to both retrieve and persist the mapping data from the associate table GroupReports. My开发者_Go百科 unit test code reveals only select SQL statement, no inserts to the mapping table.
Given my mappings, what should do to persist the mapping data?
Assuming that you're setting up your sessionfactory/session correctly (since you are getting SELECT statements) I'd bet that you aren't using transactions or flusing your session.
The recommended way to update data in NHibernate is to always use a transaction. Something like this:
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction())
{
var group = new Group {GroupName="Programmers Anonymous"};
session.Save(group);
tx.Commit();
}
This should get you going.
--UPDATE--
So after reading your other question, it seems like you want this code...
session.Save(report);
to automatically persist the groups as well. But in your mapping you have defined the groups collection as cascade="none"
. Change this to cascade="save-update"
and it will fix it.
Hope this addresses your question.
Thanks Ben, for your reply. I were not able to find my post until today. :-).
Actually I did use transaction in my code. Here is the code for my Add method:
public int Add(Report obj)
{
//set the flush mode to Never so that session.save() does not cause a flush until the commit()
//on transaction is called
_session.FlushMode = FlushMode.Never;
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(obj);
tx.Commit();//this will cause the a flush of the session
return newId;
}
catch (HibernateException)
{
tx.Rollback();
throw;
}
}
}
I am able to save the parent object with this code. In my case I am able to persist the Report object to the database. Here is my unit test code for saving both the parent and the child objects by using the many-to-many relations mapping:
const string reportCd = "TE";
const string reportName = "Test Report 6";
Report report = new Report;
report.ReportCd = reportCd;
report.ReportName = reportName;
report.IsPublicFlag = 0;
IList<Group> groups = new List<Group>();
Group group = new Group();
group.GroupId = 2;
groups.Add(group);
report.Groups = Groups;
_provider.Add(report);
The _provider object is my Dao object that has the Add method mentioned above.
Also, since the Report and Group are many-to-many objects, they contain a IList of each other. The Groups of the Report object is an IList of the Group object and the Group object has a Reports IList.
Once again, thanks for your help.
John
精彩评论