Smart Client + WCF

22 views
Skip to first unread message

Fregas

unread,
Jul 15, 2008, 2:35:57 PM7/15/08
to nhusers
I have a friend who tried to use NHibernate on a smartclient app but
gave up and went EF instead. The problem was, he wanted to use his
domain objects on the smartclient, but also be able to work
disconnected and also to call a web service to get and save the data
(presumably so he doesn't have a DB connection on every client). Does
anyone have any best practices or recommendations on this type of
scenario?

Another thing he was trying to get away from is only using data access
objects on the client. He wants real behavior w/ real domain objects
but be able to get the data from a service to enable connection
pooling

He attempted to serialize the objects and pass them over from the web
service (WCF) to the smartclient, but when he did that, NH's proxies
would lazy load everything and he would end up getting the entire
object immediately upon serialization. If he turned lazy-load off,
then NH loaded everything by default.

I really like NH but didn't know what to tell him about this
particular situation. I know in my ideal situation I wouldn't
serialize the domain objects at all, but have NHibernate or something
else magically saturate them with data provided by the web service
when needed.

Any insight is appreciated.

Thanks,
Craig

Gustavo Ringel

unread,
Jul 16, 2008, 3:37:36 AM7/16/08
to nhu...@googlegroups.com
There is no magical formula. He can usa lazy=false all the way so he don't have lazy loads (i suppose he has not deep object graphs there if he is going to serialize domain entities to web services), he can adapt the fetching strategies to what the cliente is going to use, he can use DTO's instead of domain entities to communicate with the clients

He for sure don't need all the clients to connect to the DB even if he is sending domain entites, just avoid lazy loading what the client is going to use...

There is no problem to work in this configuration with NHibernate...i will go for a DTO solution, but it will work also with domain entities, just you need to fine tune the fetching strategies...

Gustavo.

Fregas

unread,
Jul 18, 2008, 7:11:48 PM7/18/08
to nhusers
All,

I'm going to post his email to better explain what he was trying to
do. he did not want DTOs as he wanted real business objects. He
wasn't building a service he was opening up for other businesses or
over the public internet. He wanted his windows client apps to call
WCF to get domain objects and then send the domain objects back to the
server for NH to save.

Below is his email. Does anyone have any suggestions?

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Short story (I ditched it and went to the Entity Framework) and
actually like using it a lot, unlike the 400 or so Alt.Net guys that
live in Nhibernate world and gave it the vote of no confidence. Below
I'll talk about why Nhibernate is a TERRIBLE platform for SOA and
disconnected clients. For web apps, it's a great solution, but it's
just a nightmare for marshalling.

Let me first give you a rundown of the stack I was using.

NHibernate 2.0
Rhino.Commons - NHRepository
NHibernate Query Generator
Castle Windsor
--
Codesmith Nhibernate Templates for entities and mappings
--
Services - WCF
--
WPF XBAP & Silverlight

(Summary, except I wasn't doing web)
http://frickinsweet.com/ryanlanciaux.com/post/RhinoCommons2c-NHibernate-and-ASPNET-MVC.aspx

Problem # 1: Getting Rhino.Commons Repository and UnitOfWork to work
in WCF. The reason is because you want the session to be created and
ended at the beginning and end of each request. This is sort of the
worm-hole of an issue that led me into doing a week worth of
integration programming inside of WCF with Several Custom WCF Endpoint
Behaviors, Custom WCF Context Extensions, re-implementing Ayende's
Rhino.Commons Repository to support creating the UnitofWork in the WCF
Context Extensions rather than in Threading Local Storage, because
it's not always available when you need it.

I learned afterwards that there is an AspnetCompatibilityMode, which
will then have all .SVC requests actually run through the Asp.net
pipeline so that you can use the out of the box Rhino.Commons
Repository and UnitOfWork and just have it be stored in
HttpContext.Current. But talk about inefficient.

Resources I used to fix this:
http://www.ayende.com/Blog/archive/2007/06/14/Using-NHibernate-Session-Per-Request-with-WCF-Windsor-Integration.aspx

http://vanryswyckjan.blogspot.com/2008/05/integrating-castle-windsor-and.html


Problem #2: So i thought I was out of the woods when I got the session
working right, and it was actually just the beginning. The next issue
is that the proxy objects don't serialize using the default
DataContractSerializer for several reasons.
1) They don't know about the Iesi collection classes, anything that
inherits the PersistableCollections, HashedSet, Bag, etc.
2) KnownTypes don't always work for these types.
3) Any reasonable complext object graph will not work in
serialization. The serializer will work great for tree style entity
graphs, but any type that has an entity that references a parent, you
get stack overflow exceptions (supposedly .net 3.5 ServicePack1 fixes
this issue)

For 1 and 2, you can use instead the NetContractSerializer, which will
remove cross-platform compatibility, but will work if you specify the
KnownTypes for the Iesi collection. The issue there is like I said if
you have any sort of complex object graph, with circular
relationships, it fails.
Resources:
http://lunaverse.wordpress.com/2007/05/09/remoting-using-wcf-and-nhibernate/

The DataContractSerializer is the one with built in support for
circular references.
http://www.jameskovacs.com/blog/CommentView.aspx?guid=477b077c-e65e-4547-8289-4e1bc17b3de7


1) So instead, I used the DataContractSerializer, with preserve
references and replaced the proxy collections with my knownType entity
collections. Which were all just List<Entity>, no sets or anything
like that. But there are still situations in which this doesn't work.

Resources I used for this:
http://timvasil.com/blog14/post/2008/02/WCF-serialization-with-NHibernate.aspx
My implementation for Nhibernate 2.0 is at the last comment on the
page, the reason for the stack overflow is the circular references,
anything other than a complex object graph serializes fine.

Problem #3) So I scaled back my domain model, made it ridiculously
simple just to try and get out of the weeds with this crap. The
database is about 130 tables big, so it's a fairly large domain. It's
for managing product life-cycle for Pier 1, so almost every table
touches the product table. So now I get into NHibernate gripes: I
went to turn turn off lazy loading on my entities since they were
disconnected, the session wasn't available and it throws errors.
Well, there's no way to specify a way to laod the bare minimum of an
entity, instead, it will load the *ENTIRE* object graph. So when I
went to load a single Product by a sku, it executed 5k+ queries.

Nice.

So then I re-enabled lazy loading, and thought, well, i can just eager
load only what i need and then turn off lazy loading at runtime, and
send the entity over the wire after that so that it doesn't try to get
the data it doesn't need. Turns out there is no way of turning off
lazy loading at runtime, so everytime I serialized the object and it
went over the wire, it still tries to go out and load any properties.
Argh!!!

Hrmm, write my own proxies that turn off ???
http://blechie.com/WPierce/Default.aspx
http://www.ayende.com/Blog/archive/2007/04/17/Advance-Extending-NHibernate-Proxies.aspx
http://code.google.com/p/nhibernateproxygenerator/

Or there are two other solutions that would've worked in my testing.

1 ) Manual clone of every session connected proxied object over to one
of your defined entity types before you send it over the wire. (ick)

2) Use strictly DTO's instead of exposing the domain entities. So
setup Nhibernate to map to non-persistant DTO's, so it doesn't do lazy
loading, it just pre-fetches into the DTO's. Then once the client is
done with them, re-attach to a session, re-query the data, make those
changes and persist it back to the db.

Now, normally i wouldn't mind DTO's but the architecture was already
getting a little bit hairy, and the devs that actually work there
wouldn't know the first thing to do once i've left or to try to
support it.

So basically I proved to them that NHibernate is great for web apps
and terrible for SOA clients in 3 weeks.

I tried EntityFramework and got everything wired up and working in 1
day. Although it's not perfect by any means, it's still a very nice
implementation with linq and works very well with complex object
graphs.

Sorry about the Rants, and the reallllly long email, it's the first
time i've gotten to get it off my chest :-)
Let me know if you need anything at all.

HTH,

Robert

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Tommaso Caldarola

unread,
Jul 21, 2008, 4:45:22 AM7/21/08
to nhusers
On 19 Lug, 01:11, Fregas <fre...@gmail.com> wrote:
> All,
>
> I'm going to post his email to better explain what he was trying to
> do.  he did not want DTOs as he wanted real business objects.  He
> wasn't building a service he was opening up for other businesses or
> over the public internet.  He wanted his windows client apps to call
> WCF to get domain objects and then send the domain objects back to the
> server for NH to save.

Take a look to http://code.google.com/p/remoting-nhibernate/ project,
it is a skeleton of real project using Remoting, the porting to WCF is
very simple.

Tommaso

josh robb

unread,
Jul 21, 2008, 8:02:56 AM7/21/08
to nhu...@googlegroups.com
On Sat, Jul 19, 2008 at 9:11 AM, Fregas <fre...@gmail.com> wrote:
> I'm going to post his email to better explain what he was trying to
> do. he did not want DTOs as he wanted real business objects. He
> wasn't building a service he was opening up for other businesses or
> over the public internet. He wanted his windows client apps to call
> WCF to get domain objects and then send the domain objects back to the
> server for NH to save.

[long tale of woe ...]

If his solution works for him then thats fantastic. In general - I'd
make a couple of comments.

1. Passing "full business objects" over WCF probably an anti-pattern.

2. Passing NH managed entities over remoting/wcf is almost certainly
an anti-pattern.

I know of several failed projects which attempted to do what is
described above (i.e. skip using DTO's/Contracts/etc...).

The majority of problems he experienced and spent time trying to solve
are because he's trying to do something which is not recommended.

SOA is all about "Messages".

NHibernate is all about "Entities".

At first glance you might be inclined to think: I can save some time
because my entities == messages.

This is almost certainly not the case once you start building out a
system. e.g. Versioning/concurrency/graph loading/granularity are all
things which are likely to be completely differently depending on
whether your talking about messages or entities.

Saying: "Nhibernate is a TERRIBLE platform for SOA" is absolutely
true. NHibernate is an ORM. It's not an SOA platform. (However many
people use it successfully as the ORM layer for their SOA systems.)
Trying to make it into an SOA platform is a decision which is likely
to cause you significant pain.

j.

Fregas

unread,
Jul 21, 2008, 10:59:26 PM7/21/08
to nhusers
Josh,

I kind of agree with what you're saying and I kind of don't. I agree
that NH doesn't make sense in use with a SOA. I honestly am not sure
I really like SOA that much but i can see where it is necessary. I
think what he was really after was "remoting" objects in the .net
1.1/2.0 sense that Tommaso mentions and not SOA at all (even though he
calls it that.) This is a situation where both ends of the wire are
well known. He was trying to use WCF for this, which Microsoft
purposely discouraged by not creating an attribute for that type of
serialization. I also think he was pressured to use NHibernate for
this project even because it was the standard.

The need for this "remoting" I think is still out there. Having each
smart client use NH directly and create actual database connections
may be ok in some scenarios, but in others the scalability limit will
cause problems. CSLA is designed for this situation but it doesn't
seem like NHibernate is. Using DTOs with services in WCF that talk to
NH on the server seems very clunky to me. It seems like there would
be a lot of duplication and transfering data between DTOs and real
objects with behaviors. I know people have done it but I'm certain it
would frustrate me to no end.

I guess this gets into a bigger discussion of where is Domain Driven
Design and O/R Mappers such as NHibernate in an SOA world? I really
don't want to go back to splitting data from behavior but at the same
time, i don't want to make a bunch of "dumb copies" of my data using
DTOs.

craig

Gustavo Ringel

unread,
Jul 22, 2008, 4:16:20 AM7/22/08
to nhu...@googlegroups.com
Hi, DTO is not a 'dumb copy' of your entities...you don't necessary make one DTO per one Business entity...i think that having DTO's only to avoid lazy loads is a problem of not knowing how to fetch in the right way.

In general a DTO is a plain object which can collect info from several entites and send it to the user.

You may have in a graph OrderLine -> Product -> MeasureUnit but for a report for example you will send only order line with infro about the line, product name and price, measure unit name in one DTO...

It is not about sending your Business Entities throught the wire, but sending the info you need to present the customer. If you have to share your Business Entities 1 to 1 then eager fetches seem to be the best approach.

Gustavo.

Tim Scott

unread,
Jul 22, 2008, 12:26:37 PM7/22/08
to nhusers
It is quite possible to create an application using NHibernate that
sends full entities to a remote client. I have done it, and the
application has been working in production for over two years. I
wrote about it in the previously mentioned article about
NetDataContractSerializer.

I emphasize that this is not SOA. It is remoting. SOA, by definition
does not send business objects to its clients. Regarding remoting
with NHibernate, I do not recommend it until and unless there is some
means to allow lazy loading over the wire. It's just too hard and
unnatural to design a performant application that way.

Even if "remote lazy loading" could be accomplished I think I'd tend
towards SOA. A service layer that talks in DTOs only will be so much
more flexible and reusable. I know it seems like a pain to use and
create DTOs, but NHib has tools to make that less painful. In
particular check out NHibernate.Linq, which will transform results to
DTOs right in the query syntax. You only need custom transformer
classes for complex scenarios.

Fabio Maulo

unread,
Jul 22, 2008, 12:40:24 PM7/22/08
to nhu...@googlegroups.com
2008/7/22 Tim Scott <tima...@gmail.com>:

Even if "remote lazy loading" could be accomplished I think I'd tend
towards SOA.  A service layer that talks in DTOs only will be so much
more flexible and reusable.  I know it seems like a pain to use and
create DTOs, but NHib has tools to make that less painful.  In
particular check out NHibernate.Linq, which will transform results to
DTOs right in the query syntax.  You only need custom transformer
classes for complex scenarios.

or use dynamic-entities or EntityMode.Map available in NH2.1.0 (the trunk) ;)
--
Fabio Maulo

P.S. soon available EntityMode.Xml too

John Rayner

unread,
Jul 22, 2008, 5:29:46 PM7/22/08
to nhusers
I have this crazy idea that it might be possible to create a new
persister which implements IEntityPersister which would then persist
entities by posting them to a WCF service. This would have the
advantage of offering a lot of NHib goodness in the smart client
(identity management, unit of work, transparent lazy loading, etc) but
I can't really imagine that the query facilities within NHib would
work efficiently. Also, Ayende has said on a separate thread that
this would be a bad idea ...
http://groups.google.com/group/nhusers/browse_thread/thread/d7c463941272c3e6/8b6beaf81f3716a9

We adopted a different approach on my project to solve this problem.
NHib persists our entities as normal, except that all our properties
have backing fields and the fields are tagged with [DataMember]. When
WCF is deserializing a message we hook into this process to implement
our identity management and we also using DynamicProxy2 to add some
AOP-style interceptors to the entity objects. These interceptors are
resonsible for dirty-tracking of property values and this information
is then used to build update messages which we post over WCF. We also
use the AOP interceptors to implement transparent lazy-loading over
WCF.

Let me say right now, that this was very complex to get working and,
with the benefit of hindsight, I'm not sure it was the right choice.
However, we've done it now and we have the complexity nicely
encapsulated and it's all thoroughly tested.

Fabio Maulo

unread,
Jul 22, 2008, 5:44:29 PM7/22/08
to nhu...@googlegroups.com
And ?
What you are waiting to ask to share the solution you have implemented in NH.Contrib ? ;)

The first post of this thread show how many difficult is to find a solution around the NET.
If the NH community share their solution of each problem with us (all in one place) would be very useful to all.

Contact me in private mail if you are interested to share the solution.

2008/7/22 John Rayner <john....@conchango.com>:



--
Fabio Maulo

Tommaso Caldarola

unread,
Jul 23, 2008, 4:11:51 AM7/23/08
to nhusers
On 22 jul, 23:29, John Rayner <john.ray...@conchango.com> wrote:
> I have this crazy idea that it might be possible to create a new
> persister which implements IEntityPersister which would then persist
> entities by posting them to a WCF service.  This would have the
> advantage of offering a lot of NHib goodness in the smart client
> (identity management, unit of work, transparent lazy loading, etc) but
> I can't really imagine that the query facilities within NHib would
> work efficiently.  

I'm very interested to this crazy idea!!!

Tommaso

Reply all
Reply to author
Forward
0 new messages