Finally which ORM tool?

J

Jon Skeet [C# MVP]

Maybe I'm not understanding what you mean by identity management but I
use Guid fields for all my Object Ids so I don't have any "management"
issues. Guid's get created for new objects, on the client, and they stick.

With most context/session-based ORMs, the session knows which rows/
entities it has loaded. If you perform two queries which happen to
return the same rows (even if they're as associations of other
entities) you'll only have one object per row in the database.
Basically it's maintaining "database identity" (the row) in terms of
"object identity" (only one object created for that row, per context).

Without any context/session idea, you can't do that. It's unimportant
in some scenarios, and vital in others.

Jon
 
J

James Crosswell

Jon said:
With most context/session-based ORMs, the session knows which rows/
entities it has loaded. If you perform two queries which happen to
return the same rows (even if they're as associations of other
entities) you'll only have one object per row in the database.
Basically it's maintaining "database identity" (the row) in terms of
"object identity" (only one object created for that row, per context).

Without any context/session idea, you can't do that. It's unimportant
in some scenarios, and vital in others.

Hm, I'm still not sure I see the significance of this. Essentially
you're saying you want to keep only one instance of a particular object
in memory (anywhere in memory) at any one time (one object per row)??? I
can't think of any reason to require such a thing.

Or maybe what you're talking about is the behavior of the "Equals"
operator when applied to Persistent Entity classes - which basically
requires you override the Equals method and have it check for equality
of the property or properties that represent the key field for the
object in the databases (typically the Id or Oid field or whatever
you've called it). That way the ORM can compare two entities to see
whether they're the same, based on something other than the actual
object reference.

Either way I don't really see how the notion of a session is required in
any way.

Can you give me an example to demonstrate what you're talking about? I
still don't really understand.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

Jon Skeet [C# MVP]

James Crosswell said:
Hm, I'm still not sure I see the significance of this. Essentially
you're saying you want to keep only one instance of a particular object
in memory (anywhere in memory) at any one time (one object per row)??? I
can't think of any reason to require such a thing.

Suppose I fetch (within the context of a web request, for instance)
some suppliers and some customers. These both have addresses which are
stored in another table.

Now, what happens if a supplier and a customer both have the same
address, represented by the same row in the database? If I change the
details of the address of the supplier, it *should* change the details
of the address of the customer, because they're the same entity. If you
have identity management, you can make sure this happens - if you've
created two separate objects for the same address, you could change
each object independently, then issue updates to the database thinking
everything is okay when it's not.

In a nutshell, identity management allows the loaded entities to more
closely reflect the actual situation in the database.

(Within different sessions, you'd want different objects so they can
have different lifetimes etc - an update in two sessions may well cause
a concurrency violation, but that should be expected and catered for.)
 
J

James Crosswell

Jon said:
Suppose I fetch (within the context of a web request, for instance)
some suppliers and some customers. These both have addresses which are
stored in another table.

Now, what happens if a supplier and a customer both have the same
address, represented by the same row in the database? If I change the
details of the address of the supplier, it *should* change the details
of the address of the customer, because they're the same entity. If you
have identity management, you can make sure this happens - if you've
created two separate objects for the same address, you could change
each object independently, then issue updates to the database thinking
everything is okay when it's not.

In a nutshell, identity management allows the loaded entities to more
closely reflect the actual situation in the database.

(Within different sessions, you'd want different objects so they can
have different lifetimes etc - an update in two sessions may well cause
a concurrency violation, but that should be expected and catered for.)

Fair enough - so basically a problem of having the most recent data
elsewhere in the application... kind of a "Refresh" issue. If you're
only building desktop applications that use a single thread then you
could theoretically solve this with the idea of a session.

However sessions only fix the problem for single threaded classic
client/server apps. If you've got a multi-threaded or even just a
multi-user application where that customer is retrieved by multiple
threads/clients (potentially running on multiple machines), you've got
exactly the same issue and the idea of a session won't help you (since
each client has it's own session).

I think the idea of sessions is a limited solution to the problem and a
more comprehensive data synchronization framework is required. SQL
Server 2005 has something that kind of addresses this issue, but only
once the data is posted to the databases and only for clients that have
a direct connection to the databases. In the apps I'm building I have a
middle tier and various clients that connect to the middle tier, so
those SQL Server 2005 notifications are a good start but:
1. They only work with SQL Server 2005
2. They only notify the middle tier

As such, I always end up rolling out my own solution/framework to have
the middle tier notify clients of changes that have been made by other
clients.

Basically, I think the designers of ORM frameworks who decided they
"needed" sessions to "solve" identity management problems created a
solution that isn't very generic and only solves the problem in one
particular case - i.e. for single-threaded and single-user desktop apps.
Inadvertently, they've also created a problem for n-tier apps though,
which don't maintain a single session for the lifetime of the app but
more commonly service requests from multiple users and opperate on a one
session per thread and a one thread per request basis.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

Jon Skeet [C# MVP]

James Crosswell said:
Fair enough - so basically a problem of having the most recent data
elsewhere in the application... kind of a "Refresh" issue. If you're
only building desktop applications that use a single thread then you
could theoretically solve this with the idea of a session.

No, it's not a case of a refresh issue - it's an aliasing issue.

If you've got two objects in memory which are theoretically the same
database entity - having come from the same database within the same
transaction and representing the same row - then I think you've lost
something in the mapping. As I say, sometimes it's not an issue, but in
other cases it can be very useful to know that you'll only ever see one
copy of one entity.
However sessions only fix the problem for single threaded classic
client/server apps. If you've got a multi-threaded or even just a
multi-user application where that customer is retrieved by multiple
threads/clients (potentially running on multiple machines), you've got
exactly the same issue and the idea of a session won't help you (since
each client has it's own session).

No, you've got a different issue - and one you've already got within
any system.

Basically, I think the designers of ORM frameworks who decided they
"needed" sessions to "solve" identity management problems created a
solution that isn't very generic and only solves the problem in one
particular case - i.e. for single-threaded and single-user desktop apps.

No, I think you're missing the point, which may well be due to me not
describing it terribly well.
Inadvertently, they've also created a problem for n-tier apps though,
which don't maintain a single session for the lifetime of the app but
more commonly service requests from multiple users and opperate on a one
session per thread and a one thread per request basis.

Yes, and it can be equally important there, because it's an aliasing
issue rather than a concurrency issue.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Wiktor said:
yes but only if you consider webservices as a part of a soa. and not
every single web service application must be a soa.

I consider an anti-pattern in all cases except 2 tier with
public cloud between client app and database. And that must
be a pretty rare setup these days.

Arne
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Frans said:
Though in THAT case, a webservice is the most slowest way to implement
a tier in an n-tier application, as it doesn't scale that well in that
way due to the chattyness of tier communication and the slowness of
serialization/deserialization. (try to pull 100,000 entities over the
wire to process them on the client, while you could have done the
processing on the server)

It scales fine (assuming write through for updates).

It does not perform well.

Good scalability and good performance is not the same.

Arne
 
F

Frans Bouma [C# MVP]

Jon said:
On Oct 11, 9:06 am, "Frans Bouma [C# MVP]"

I think the central context/session design which is common
among most O/R mappers is the cause of many of these problems, and
which is also why we didn't use this pattern in LLBLGen Pro. Linq
to Sql / Entities both have the same attach/detach hell btw.

Without a context/session design, how do you ensure identity
management though?
Just curious. I must actually look at LLBLGen Pro some time...

With so called Context objects which define a semantical uniquing
context in memory. So although they're called 'context', they're just
meant for uniquing purposes in-memory. You can pass a Context object to
the o/r core and it will then be used to create unique instances.

It has the advantage that you can have multiple unique boundaries
within an application, thread or even routine, if you want to.

In most situations however, unique object instances per entity
instance (== data) isn't really required, as you're running into
concurrency issues anyway, as all data is outside the DB so in one way
or the other, stale. THis means that even if you use in thread A unique
objects for thread A, other threads have different instances (as .NET
doesn't have cross appdomain object awareness) and therefore 'uniquing'
isn't really useful in thread A anyway, unless A's logic has to be sure
it's working with the same objects everywhere in thread A, which is
solved by our context object (which has no fetch / tracking
capabilities, it just allows you to get unique instances)

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
F

Frans Bouma [C# MVP]

Jon said:
No, it's not a case of a refresh issue - it's an aliasing issue.

If you've got two objects in memory which are theoretically the same
database entity - having come from the same database within the same
transaction and representing the same row - then I think you've lost
something in the mapping. As I say, sometimes it's not an issue, but
in other cases it can be very useful to know that you'll only ever
see one copy of one entity.

Though, in-memory entity objects (the class instances) are still
buckets, holding in-memory copies (mirrors) of the entity instances in
the db.

Though it can be important indeed to have a reference to the same
entity bucket instance. BUt this is all about semantics. As soon as you
begin to think it's not semantics, you're lost.

The thing is: uniquing (the mechanism to get unique entity bucket
instances per entity instance) is a semantical issue, as the unique
instance only has to be unique in a given semantical context, i.e. in a
given block of code or in a given routine, or in a given graph.

So what you want is something like:
Context c = new Context(); // define the uniquing object.
// fetch customer entities by passing c to the o/r core so all entities
// are in c afterwards
....

// at a later point in the routine you might want to obtain the unique
// instance for a customer entity E.
CustomerEntity customer = (CustomerEntity)c.Get(
new CustomerEntityFactory(), "CHOPS");

at this point, customer is either null (not found) or has the reference
to the customer already in the context.

It's in a way a local cache, but as I wrote some time ago on my blog
about caches in o/r mappers: the main reason why there are caches in
o/r mappers is for uniquing.

The sad thing is though with these caches that they're tied to the
session/context in most cases. You actually want to tie them to the
method/object/area where you're USING the entities, as you want to use
uniquing THERE, throughout the method/object/area.
No, I think you're missing the point, which may well be due to me not
describing it terribly well.

I think he perfectly got the point :). The attach/detach hell is
related to this/a result of this.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
F

Frans Bouma [C# MVP]

Arne said:
It scales fine (assuming write through for updates).
It does not perform well.
Good scalability and good performance is not the same.

if you have to connect to a service for every step you take in a
process (sequence), the service is used in a 'chatty' way, which means
that scalability is going down, because adding more clients will
increase the # of connections to a point where it's physically not
possile to handle them, which is reach very quickly IMHO, with chatty
services.

True, sending 1 message to pull 100,000 objects over the wire is just
performing poorly even though the 1 message sent isn't a scalability
issue, I didn't make that clear very well.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

On Oct 12, 9:25 am, "Frans Bouma [C# MVP]"

Though it can be important indeed to have a reference to the same
entity bucket instance. BUt this is all about semantics. As soon as you
begin to think it's not semantics, you're lost.

Sure, it's semantics - but I believe semantics are incredibly
important!
The thing is: uniquing (the mechanism to get unique entity bucket
instances per entity instance) is a semantical issue, as the unique
instance only has to be unique in a given semantical context, i.e. in a
given block of code or in a given routine, or in a given graph.

And that *context* is the context that you should be using as your
session/context.

It's in a way a local cache, but as I wrote some time ago on my blog
about caches in o/r mappers: the main reason why there are caches in
o/r mappers is for uniquing.

Sure, I have no problem with that.
The sad thing is though with these caches that they're tied to the
session/context in most cases. You actually want to tie them to the
method/object/area where you're USING the entities, as you want to use
uniquing THERE, throughout the method/object/area.

You've just said it *should* be about context - so you just need to
make sure you use the ORM context appropriately.
I think he perfectly got the point :). The attach/detach hell is
related to this/a result of this.

Oh that part I agree with - but not that "uniquing" is designed to
solve single-threaded, single-user desktop apps. I can't say I've ever
found it hellish though.

Jon
 
J

James Crosswell

Jon said:
No, it's not a case of a refresh issue - it's an aliasing issue.

If you've got two objects in memory which are theoretically the same
database entity - having come from the same database within the same
transaction and representing the same row - then I think you've lost
something in the mapping. As I say, sometimes it's not an issue, but in
other cases it can be very useful to know that you'll only ever see one
copy of one entity.

OK, well let me ask a fairly simple question. How would you have
typically solved this problem using a solution based on pure ADO.NET? In
a desktop application you might have a static class or member property
somewhere to manage the "Unique" object that you're dealing with. In a
multi-tier application you might have the server maintain and manage a
unique copy of the object in some kind of global cache (which again
would be some kind of static class/member variable that only the server
managed).

However, all of that talks about a fairly obscure use of persistent
objects that I have not encountered (nor even discussed until this
thread) in my entire career. The fact is, ORMs like XPO and nHibernate
REQUIRE you to use a session to work with persistent objects even though
it's only necessary (judging from what I'm starting to understand here)
in the smallest fraction of circumstances.

Surely it would be possible to overload the Save/Load methods of the
persistence framework to either take a session parameter or not. Or
maybe have two PersistenceController classes - one which is implicitly
sessionless and another which is not.

I simply can't see that forcing everyone to use sessions (whether they
need them or not) is the most elegant solution to this problem and,
indeed, if you've ever done any n-tier work you'll know that it's quite
the opposite for n-tier frameworks... it is a problem, not a solution.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

Jon Skeet [C# MVP]

OK, well let me ask a fairly simple question. How would you have
typically solved this problem using a solution based on pure ADO.NET? In
a desktop application you might have a static class or member property
somewhere to manage the "Unique" object that you're dealing with. In a
multi-tier application you might have the server maintain and manage a
unique copy of the object in some kind of global cache (which again
would be some kind of static class/member variable that only the server
managed).

In pure ADO.NET you wouldn't have had an object tree which was meant
to represent the same state as the server, so the aliasing wouldn't
have been apparent.
However, all of that talks about a fairly obscure use of persistent
objects that I have not encountered (nor even discussed until this
thread) in my entire career. The fact is, ORMs like XPO and nHibernate
REQUIRE you to use a session to work with persistent objects even though
it's only necessary (judging from what I'm starting to understand here)
in the smallest fraction of circumstances.

So if you don't care about session lifetimes, just create a session
for each separate query - it's very easy to do.
Surely it would be possible to overload the Save/Load methods of the
persistence framework to either take a session parameter or not. Or
maybe have two PersistenceController classes - one which is implicitly
sessionless and another which is not.

Again, it would be very easy for you to do that yourself, just
creating the session when you need to.
I simply can't see that forcing everyone to use sessions (whether they
need them or not) is the most elegant solution to this problem and,
indeed, if you've ever done any n-tier work you'll know that it's quite
the opposite for n-tier frameworks... it is a problem, not a solution.

I've done plenty of n-tier work, and it's *not* the opposite for n-
tier frameworks. I suspect it depends on what you really want the ORM
system to do for you, but I've never regarded the session handling as
a problem, especially as Hibernate/nHibernate provide the ability to
"re-attach" an object from a previous session into a new one when you
want to.

The "Hibernate in Action" book (back when it was called that - I
haven't read the new version thoroughly) describes it all in detail
and I've never found it painful.

Jon
 
T

Tigger

James Crosswell said:
OK, well let me ask a fairly simple question. How would you have typically
solved this problem using a solution based on pure ADO.NET? In a desktop
application you might have a static class or member property somewhere to
manage the "Unique" object that you're dealing with. In a multi-tier
application you might have the server maintain and manage a unique copy of
the object in some kind of global cache (which again would be some kind of
static class/member variable that only the server managed).

I also would like to see a nice way to handle this sort of problem using
ADO.

I've developed our own in house ORM. Initially for use in webservices and
later in windows apps.

I wanted the business developer to be able to concentrate on the business
logic and not have to worry about issues like those discusses here.

Part of this was that they could navigate through the entities without
worry. This eventually came to the solution of a entity cache. I have not
implemented a session based version yet, as it has not been needed. So for a
single application, there will only ever be one copy of a database row in
memory at one time.

An example of the issues this resolved for me. The shopping cart:

A Cart is loaded into memory
It is modified to use a new currency
It asks each entry in it to re-calculate their-prices
Each entry accesses their cart to get the current currency

Without entity caching the entries would load the last cart from the
database, with the wrong currency!

Tigger

p.s. I recently tried to create a simple app using ADO.NET (first time
since .Net 2.0). I quickly gave up and went back to our ORM. I'll have to
admit this was partly due to the poor integration between MySQL and Visual
Studio. I'm glad this app now usese our ORM. Its so much nicer to work with
business objects instead of Tables and Rows.
 
J

James Crosswell

Jon said:
In pure ADO.NET you wouldn't have had an object tree which was meant
to represent the same state as the server, so the aliasing wouldn't
have been apparent.

Wouldn't you? What kind of things would you be passing back and forth
between your n-tier application server and client in an pure ADO.NET
implementation of the server? Did you pass datasets back and forth? I
sure didn't.
So if you don't care about session lifetimes, just create a session
for each separate query - it's very easy to do.

What I do currently is the following (Pseudocode):

void Save(object objectToSave)
{
using (Session session = InsertORMHere.NewSession())
{
object fetched = session.GetByKey(objectToSave.Oid);
if (fetched == null)
{
session.Save(objectToSave);
}
else
{
fetched.CopyFrom(objectToSave);
session.Save(fetched);
}
}
}

Which is fine and with a bit of reflection (in the implementation of the
CopyFrom method, to copy object properties across) this works (and
avoids an insert where an update should have occurred because of the
whole business with sessions)... but it is, none the less, a workaround.

I'm not sure if you're playing the devils advocate or if you're just
generally hostile to change but it seems to me that what I'm suggesting
is certainly an improvement over the existing frameworks which REQUIRE
me to write the above workaround because they REQUIRE sessions, even
though these are not required in order for these ORMs to do their work.
The idea of a session is only required by a select portion of the people
using these ORMs so it seems insane to impose it on the rest of the
applications using these ORMs... It's like forcing every application to
choose a TCP/IP port, even if they don't use TCP/IP - what's the
point??? The only thing it achieves is to inconvenience developers using
these frameworks.
Again, it would be very easy for you to do that yourself, just
creating the session when you need to.

Yes but why should I? Why the heck isn't it built into the frameworks
and why do they cling needlessly to a dependence on sessions when the
OPTION to use sessions would suffice.
I've done plenty of n-tier work, and it's *not* the opposite for n-
tier frameworks. I suspect it depends on what you really want the ORM
system to do for you, but I've never regarded the session handling as
a problem, especially as Hibernate/nHibernate provide the ability to
"re-attach" an object from a previous session into a new one when you
want to.

I said sessions created a problem in n-tier (where they don't in desktop
apps) and if you've done a lot of n-tier work then you must realize this
is the case, since sessions in n-tier typically get created and
destroyed on a per thread basis and threads get created/destroyed on a
per request basis... requiring the workaround I described above in order
to effect updates.

I wasn't aware of the re-attach behavior in nHibernate though... that
sounds interesting and would at least reduce the amount of needless code
I write to one line. I'll try to track down some info on this on the net
(although one of my projects is using XPO and they don't have such a
"feature"). Thanks for the tip.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

Jon Skeet [C# MVP]

James Crosswell said:
Wouldn't you? What kind of things would you be passing back and forth
between your n-tier application server and client in an pure ADO.NET
implementation of the server? Did you pass datasets back and forth? I
sure didn't.

So if you *have* got an object tree, do you just not care about
aliasing at all? Often it's not a case of returning results to the
client - it's manipulation at the server end which may well being
sensitive to aliasing issues.

I'm not sure if you're playing the devils advocate or if you're just
generally hostile to change but it seems to me that what I'm suggesting
is certainly an improvement over the existing frameworks which REQUIRE
me to write the above workaround because they REQUIRE sessions, even
though these are not required in order for these ORMs to do their work.

The decision to be session-based or not is pretty fundamental to an
ORM. If you don't want to use sessions, use an ORM which isn't session-
based, such as LLBLGen - but please don't try to suggest that no ORMs
should use sessions and manage aliasing and identity issues just
because they happen not to be issues for you.

That's the great thing about having a choice of frameworks. I have to
say that the fact that most ORM frameworks I've come across *do* have
identity management suggests that the requirement for it isn't as rare
as you seem to be making it out to be. If sessions have no benefit for
most people, why do you think the framework developers include them?
I said sessions created a problem in n-tier (where they don't in desktop
apps) and if you've done a lot of n-tier work then you must realize this
is the case, since sessions in n-tier typically get created and
destroyed on a per thread basis and threads get created/destroyed on a
per request basis... requiring the workaround I described above in order
to effect updates.

You need to distinguish between the idea of a per-request session and a
"per user transaction" session. Again, Hibernate in Action deals with
this very well.
I wasn't aware of the re-attach behavior in nHibernate though... that
sounds interesting and would at least reduce the amount of needless code
I write to one line. I'll try to track down some info on this on the net
(although one of my projects is using XPO and they don't have such a
"feature"). Thanks for the tip.

I can't say I've looked at whether NHibernate itself has this, but I
should imagine it does given how it's present in Hibernate.

The Hibernate authors have put in a *lot* of thought when it comes to
this kind of thing, and they're certainly *not* just thinking of
desktop client/server apps.
 
J

James Crosswell

Jon said:
The decision to be session-based or not is pretty fundamental to an
ORM. If you don't want to use sessions, use an ORM which isn't session-
based, such as LLBLGen - but please don't try to suggest that no ORMs
should use sessions and manage aliasing and identity issues just
because they happen not to be issues for you.

I think you're intentionally mashing my words up here. I never said any
such thing. I said that ORMs should not REQUIRE us to use sessions in
order to persist and load objects.

What I did NOT say (and which you suggested I did) is that ORMs
shouldn't provide session capabilities. I think they're just fine and
dandy and a nice feature. However I see no reason why they shouldn't be
OPTIONAL and I've provided some pretty good examples why they should be...
That's the great thing about having a choice of frameworks. I have to
say that the fact that most ORM frameworks I've come across *do* have
identity management suggests that the requirement for it isn't as rare
as you seem to be making it out to be. If sessions have no benefit for
most people, why do you think the framework developers include them?

Why do we have TCP and TCP/IP ports if developers don't use TCP/IP? The
fact is, LOTS of applications use TCP/IP - but that's no reason to force
ALL applications to use it. I'm making pretty much the same case here
but you don't seem to be following my reasoning very well.
You need to distinguish between the idea of a per-request session and a
"per user transaction" session. Again, Hibernate in Action deals with
this very well.

Unless by per user transaction you mean a one thread per client model
for the server threads then I don't see how this makes a difference.
With such a threading strategy the server creates a thread for a client
application when it first connects/authenticates and leaves this thread
running for the duration of a user's "connection" to the application
server... something you could do with a connection based protocol like
TCP/IP but stateless protocols like HTTP make this very difficult.
Besides which these servers don't scale very well (as soon as you get
any volume on the server they grind to a halt swapping out to disk for
lack of memory because they've got far too many threads lying around
with "session" information in them).

Otherwise though, you're not guaranteed to get the same thread from the
thread pool on the server in the request that you make to Save a
persistent object as you did in the request that you made to Fetch that
persistent object from the app server in the first place - and thus
you're not guaranteed to get the same session (with your ORM).

So although a distinction between per-request and per-user sessions is
perhaps relevant for a one thread per client thread strategy, I try to
stay away from such a beast (for the reasons above). Stateful servers
are just plain unreliable, by design.
The Hibernate authors have put in a *lot* of thought when it comes to
this kind of thing, and they're certainly *not* just thinking of
desktop client/server apps.

Well the DevExpress guys put a lot of thought into XPO - it's a really
well designed product... very easy to use etc. and it's evident that
they put a huge amount of effort into developing an extremely polished
framework there. However, at the same time it's clear that very little
of that care and attention was given to how XPO could be used in an
n-tier solution until very recently (at the insistence of many
customers, myself among them, and they haven't as yet released anything
in this regard so I'm still waiting to see what the results will be)...

I'm not shy of pointing out possible improvements, even for very mature
frameworks. Whilst often this is simply a result of my lack of knowledge
of the frameworks features (in which case usually someone sets me right
quick enough, which is ideally what I'm after) I don't think this is the
case here.

You're quite right, nHibernate is not the only ORM to incorporate the
idea of sessions and, indeed, it's not the only one to make it
obligatory (XPO being case in point). This is exactly my frustration
though - I think they all do so unnecessarily and, as yet, I've yet to
hear a convincing argument to the contrary.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

Jon Skeet [C# MVP]

James Crosswell said:
I think you're intentionally mashing my words up here. I never said any
such thing. I said that ORMs should not REQUIRE us to use sessions in
order to persist and load objects.

What I did NOT say (and which you suggested I did) is that ORMs
shouldn't provide session capabilities. I think they're just fine and
dandy and a nice feature. However I see no reason why they shouldn't be
OPTIONAL and I've provided some pretty good examples why they should be...

Let me rephrase then:

It is easier to write an ORM system which has a rich session system if
you force sessions to be used everywhere: it means that every layer of
the ORM framework code can rely on sessions being available.

If you don't want to use sessions, I would suggest you use an ORM which
makes them optional, understanding that there may well be session-based
features which aren't available because the sessions aren't pervasive
in that system.
Why do we have TCP and TCP/IP ports if developers don't use TCP/IP? The
fact is, LOTS of applications use TCP/IP - but that's no reason to force
ALL applications to use it. I'm making pretty much the same case here
but you don't seem to be following my reasoning very well.

I don't see the analogy at all, I'm afraid.
Unless by per user transaction you mean a one thread per client model
for the server threads then I don't see how this makes a difference.

I mean a session which is potentially split over multiple client/server
requests.

Otherwise though, you're not guaranteed to get the same thread from the
thread pool on the server in the request that you make to Save a
persistent object as you did in the request that you made to Fetch that
persistent object from the app server in the first place - and thus
you're not guaranteed to get the same session (with your ORM).

Absolutely, and Hibernate certainly isn't based on the idea of
retrieving the original thread for a subsequent request.
So although a distinction between per-request and per-user sessions is
perhaps relevant for a one thread per client thread strategy, I try to
stay away from such a beast (for the reasons above). Stateful servers
are just plain unreliable, by design.

The distinction is relevant in a more general way, but I don't have the
time or expertise to go into details here. I really do thoroughly
recommend the Hibernate book though - even if you never touch
Hibernate, it discusses a lot of very useful issues which are likely to
affect developers doing *any* database-related development.
Well the DevExpress guys put a lot of thought into XPO - it's a really
well designed product... very easy to use etc. and it's evident that
they put a huge amount of effort into developing an extremely polished
framework there. However, at the same time it's clear that very little
of that care and attention was given to how XPO could be used in an
n-tier solution until very recently (at the insistence of many
customers, myself among them, and they haven't as yet released anything
in this regard so I'm still waiting to see what the results will be)...

I'm not shy of pointing out possible improvements, even for very mature
frameworks. Whilst often this is simply a result of my lack of knowledge
of the frameworks features (in which case usually someone sets me right
quick enough, which is ideally what I'm after) I don't think this is the
case here.

You're quite right, nHibernate is not the only ORM to incorporate the
idea of sessions and, indeed, it's not the only one to make it
obligatory (XPO being case in point). This is exactly my frustration
though - I think they all do so unnecessarily and, as yet, I've yet to
hear a convincing argument to the contrary.

This is why I'm recommending the Hibernate book: it explains the
session handling, including the pitfalls and the reasons behind it,
very well.

When one framework forces you into a particular and irritating mindset,
it can be seen as a mistake. When several (including the most commonly
used ones) do so, it's worth taking a step back and looking for the
underlying reasons. The experts are best placed to do that, and I don't
claim to be an expert in ORM in general.

(As another couple of data points, LINQ to SQL has the same session
bias, and I believe that the ADO.NET Entity Framework does too.)
 
J

James Crosswell

Jon said:
When one framework forces you into a particular and irritating mindset,
it can be seen as a mistake. When several (including the most commonly
used ones) do so, it's worth taking a step back and looking for the
underlying reasons. The experts are best placed to do that, and I don't
claim to be an expert in ORM in general.

Aye, that's pretty much what I'm trying to get my head around... still
not making much ground though.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Frans said:
if you have to connect to a service for every step you take in a
process (sequence), the service is used in a 'chatty' way, which means
that scalability is going down, because adding more clients will
increase the # of connections to a point where it's physically not
possile to handle them, which is reach very quickly IMHO, with chatty
services.

This type of web services are vertical scalable to some point.

And horizontal scalable.

They scale very nicely.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top