Nhibernate over WCF

12 views
Skip to first unread message

V

unread,
Jun 27, 2009, 10:14:15 PM6/27/09
to nhusers
Hi,

I understand that this topic has been beaten to death so many times,
but I need to ask this question about using nhibernate with WCF (or
may be asmx webservices too).

Say I have a Parent and Child class. Now client gets the object of
parent (also carrying some child dto objects as collection) from the
webservice. Then client modifies the parent object and also carries
out three operations on child collection (adds an object, deletes an
object and modifies one object). After that this whole graph is sent
back to WCF service using another method to save it. Now my question
is, do I have to use Lock method only on the parent to attach it to
the session? How will the three operations on children be carried out
(insert 1, delete 1 and update 1).

I hope I have been able to explain my requirement. Without a proper
solution our company may decide to tilt towards MS entity framework
(We had one MS evangelist in our premises the other day and he
promised sun, moon and stars to our CTO). We have been using
NHibernate (via castle activerecord) for quite a period (a little over
2.5 years but only in WinForms applications in one-tier mode) that I
would hate to let it go.

Thanks
Vijay

Fabio Maulo

unread,
Jun 28, 2009, 1:26:16 AM6/28/09
to nhu...@googlegroups.com
If your CTO likes the sky I think you shouldn't fight with him; when you will have a problem remember that the sky is so near to god that you can ask him to solve your problem. ;)

2009/6/27 V <vijay....@gmail.com>



--
Fabio Maulo

Fabio Maulo

unread,
Jun 28, 2009, 1:29:05 AM6/28/09
to nhu...@googlegroups.com
You can use Merge, Update or SaveOrUpdate to reattach an entity to a fresh session but the final behaviour will depend on the type of the collection.


2009/6/27 V <vijay....@gmail.com>



--
Fabio Maulo

Oskar Berggren

unread,
Jun 28, 2009, 4:50:11 AM6/28/09
to nhu...@googlegroups.com
There is of course the option of not sending your actual domain
objects remotely, instead using simple parameters and/or DTOs and
letting your domain objects stay on the server side.

/Oskar


2009/6/28 V <vijay....@gmail.com>:

Fabio Maulo

unread,
Jun 28, 2009, 9:46:41 AM6/28/09
to nhu...@googlegroups.com
2009/6/28 Oskar Berggren <oskar.b...@gmail.com>


There is of course the option of not sending your actual domain
objects remotely, instead using simple parameters and/or DTOs and
letting your domain objects stay on the server side.

And the sun the moon and the stars ? 

Oskar, your solution is for a mere mortal and I don't think is what the CTO is looking for.
;)

--
Fabio Maulo

V

unread,
Jun 28, 2009, 10:52:19 AM6/28/09
to nhusers
> > There is of course the option of not sending your actual domain
> > objects remotely, instead using simple parameters and/or DTOs and
> > letting your domain objects stay on the server side.
>
> And the sun the moon and the stars ?
>
> Oskar, your solution is for a mere mortal and I don't think is what the CTO
> is looking for.
> ;)

CTO does not know C# at all. CTO is CTO because he runs the company
and signs my pay cheque. All he wants is a promise of faster
development of our applications using WCF + WinForms / WPF. I have
already suggested using DTO's. I have created a small demo of WCF
service using Entity Framework where I pass some objects to and fro to
show various operations for insert, update and delete. Now I have to
create a WCF service using NH so that we can compare the two side-by-
side.

The only thing I did not like about entity framework was that if a
parent is being updated along with some child objects in its
collection, I have to follow these steps:

1) insert -> add object to context (analogous to NH session) but going
through all the items in the list and adding only the items which are
new (by checking unassigned PK)
2) delete -> I have to bring back a list of id's of items to be
deleted because they are missing from the parent collection due to
removal from list, and then use those id's to delete objects
indivdually.
3) update -> this is more complex as every item that needs to be
updates must be loaded from the database into the context, updated
with new values and then persisted with method SaveChanges (from
framework itself) which issues update statement if any property has
changed from it original value from database.

This is where we want to minimise coding.

In my question I wanted to know was if I attach a parent to session
and save it, will it take care of updating child objects also by
attaching them to session and issuing proper statements for insert/
update/delete?

I will give it a try myself tomorrow, I was wondering if somebody else
had experience in this area and could guide me.

Thanks
V

Germán Schuager

unread,
Jun 28, 2009, 11:00:26 AM6/28/09
to nhu...@googlegroups.com
You will need to set the "cascade" setting in the mappings. Take a look at the docs.

Fabio Maulo

unread,
Jun 28, 2009, 11:08:05 AM6/28/09
to nhu...@googlegroups.com
2009/6/28 V <vijay....@gmail.com>

In my question I wanted to know was if I attach a parent to session
and save it, will it take care of updating child objects also by
attaching them to session and issuing proper statements for insert/
update/delete?

Yes but, as I said in the second answer, the final behaviour (of what NH will do) depend on the type of the collection (an <set> will have a different behaviour of a <bag>).

--
Fabio Maulo

P.S. I'm assuming you know about the attribute "cascade" in the mapping.

V

unread,
Jun 28, 2009, 4:15:54 PM6/28/09
to nhusers
> Yes but, as I said in the second answer, the final behaviour (of what NH
> will do) depend on the type of the collection (an <set> will have a
> different behaviour of a <bag>).

Thanks to you guys for all the support.

I fully understand that the final behavior would be defined by the
cascade and also type of the collection. I will give it a try when I
go to work tomorrow.

V

V

unread,
Jun 30, 2009, 1:23:07 AM6/30/09
to nhusers
On Jun 28, 9:15 pm, V <vijay.s.g...@gmail.com> wrote:
> > Yes but, as I said in the second answer, the final behaviour (of what NH
> > will do) depend on the type of the collection (an <set> will have a
> > different behaviour of a <bag>).
>

Hello again friends.

I created a small demo and it works fine except one issue. If I get a
parent with some children from WCF, remove one child, add a new one,
update an existing one, and finally save the parent again, the child
that was deleted from client does not get deleted from database. I
dumped SQL into log file and saw there was no delete statement issued.
I am posting my hbm files and the demo code used for saving the
parent.

Parent HBM:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-
access="">
<class name="BackendService.Parent, FrontEnd, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null" table="tbl_parent"
xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-
update="true">
<id name="Id" type="Guid" unsaved-
value="00000000-0000-0000-0000-000000000000" column="id">
<generator class="guid" />
</id>
<property name="Description" type="String">
<column name="description" />
</property>
<property name="Age" type="Int32">
<column name="age" />
</property>
<set name="Children" lazy="true" cascade="all-delete-orphan"
fetch="select" inverse="true">
<key column="Parent_id" />
<one-to-many class="BackendService.Child, FrontEnd,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>
</class>
</hibernate-mapping>

Child HBM:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-
access="">
<class name="BackendService.Child, FrontEnd, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null" table="tbl_child"
xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-
update="true">
<id name="Id" type="Guid" unsaved-
value="00000000-0000-0000-0000-000000000000" column="id">
<generator class="guid" />
</id>
<property name="Description" type="String">
<column name="description" />
</property>
<property name="Age" type="Int32">
<column name="age" />
</property>
<many-to-one cascade="save-update" fetch="join" name="ParentRef"
column="parent_id" />
</class>
</hibernate-mapping>

Code:

public void SaveParent(Parent parent)
{
try
{
var sessionFactory = MappingHelper.CreateSesionFactory
();
using (var session = sessionFactory.OpenSession())
{
session.FlushMode = FlushMode.Never;
session.Replicate(parent,
ReplicationMode.Overwrite);
session.SaveOrUpdate(parent);
// if used alone, SaveOrUpdate causes Expected 1,
Actual 0 exception and it does not save children
session.Flush();
}
}
catch(Exception ex)
{
LogException(ex);
throw;
}
}

PS: MappingHelper.CreateSesionFactory(); creates session factory only
once, saves it in a static variable and returns the same on every
subsequent invocation.

Thanks
V
Reply all
Reply to author
Forward
0 new messages