unitofwork in a distributed environment

Posts   
 
    
kulki
User
Posts: 26
Joined: 20-Dec-2004
# Posted on: 20-Jan-2005 06:52:09   

I am having difficulty dealing with this situation. UI adds objects to the UnitOfWork and then calls Commit(). UnitOfWork() itself gets sent across to the server side where the actual updates are performed. Its now possible that during this update process the objects themselves might be modified. Somehow all the original object references must be updated to point to the newly created ones.

I hope I am on the right track here.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 20-Jan-2005 10:02:52   

Commit() is done on the server, I think, as the GUI should call a server method and pass the UnitOfWork object.

In distributed environments, you work disconnected, that's the key: so you think in these steps: 1) create containers (entity objects) 2) add data to/load data in containers (from server for example) 3) show data in modifiers (forms) 4) data is modified and collected for persistence 5) collected data is send to server for persistence 6) process is ended

At stage 6) the state should be considered void. It's up to you to ignore that and keep data around on the client. But as you work disconnected, there is no feedback from the server for example if you send an entity from client to server and it is saved there: you won't all of a sudden have an outofsync entity on the client, as that's just a copy of the object on the server. So if you want to keep on working on the client with the data, you have to consider that after step 6 you have to rewind to 1) or 2), unless you know what you can keep (read-only data for example).

If you're in 6) and you rewind to 4), you're modifying data which is out of sync with the server. LLBLGen Pro doesn't provide you with a layer which takes care of that, as I believe you should control that yourself, because only then the developer has full control over when what happens. So when you send a UoW to the server, you have to realize you're in 5) moving to 6) and it's all over for that process. If that's not the case, then you shouldn't move from 4) to 5) there, but wait and persist the data later.

Frans Bouma | Lead developer LLBLGen Pro
kulki
User
Posts: 26
Joined: 20-Dec-2004
# Posted on: 20-Jan-2005 19:11:13   

Thank you for a very well though out answer. Let me try to give you an example of a scenario which bothers me. This is in the context of a ASP.NET application. As soon as the user logs in I save the User object into a session Variable. Sometime later the user might decide to change his FirstName. Since there is no IdentityMap, its very possible that a new Instance of the user could be created. The FirstName is modified and then saved. However now the copy of the User object stored in the session variable is now out of sync with the DataBase. If somehow this copy could have been informed that its out of sync and made to refresh its data then it would have been great. If you have the time take a look at ActiveObjects (CSLA framework)

kulki
User
Posts: 26
Joined: 20-Dec-2004
# Posted on: 20-Jan-2005 19:15:17   

Otis wrote:

If you're in 6) and you rewind to 4), you're modifying data which is out of sync with the server. LLBLGen Pro doesn't provide you with a layer which takes care of that, as I believe you should control that yourself, because only then the developer has full control over when what happens. So when you send a UoW to the server, you have to realize you're in 5) moving to 6) and it's all over for that process. If that's not the case, then you shouldn't move from 4) to 5) there, but wait and persist the data later.

Well I think a framework must not automatically refresh the appropriate references, but should it not atleast raise events to inform that the object has been modified and therefore needs to be refreshed.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 21-Jan-2005 10:25:46   

kulki wrote:

Thank you for a very well though out answer. Let me try to give you an example of a scenario which bothers me. This is in the context of a ASP.NET application. As soon as the user logs in I save the User object into a session Variable. Sometime later the user might decide to change his FirstName. Since there is no IdentityMap, its very possible that a new Instance of the user could be created. The FirstName is modified and then saved. However now the copy of the User object stored in the session variable is now out of sync with the DataBase.

With an identity map you won't be helped either: what if your app runs in a webfarm scenario?

What you should do is to give an entity a uniquely identifying attribute, a PK, and one which is not easily changed, for example an artificial ID. Firstname + Lastname is not good enough. In your scenario, the new user is saved when its created. When he changes his name attribute, that's ok, save it again. If another entity with the same data is created, it's another entity, and you should check when you're creating THAT entity if it is a duplicate or not.

If somehow this copy could have been informed that its out of sync and made to refresh its data then it would have been great. If you have the time take a look at ActiveObjects (CSLA framework)

That's impossible to implement. Sure it works in a desktop app with a local database, but not in a webapp. First of all, there has to be a central system which controls every access to the db. In a webapp this is not possible, as asp.net performs appDomain recycling. Furthermore, a webfarm kills the concept also. And last but not least: webapps are more or less stateless, no matter how hard microsoft tries to tell you otherwise. It looks like they're not, but they are.

Well I think a framework must not automatically refresh the appropriate references, but should it not atleast raise events to inform that the object has been modified and therefore needs to be refreshed.

How can it know something has changed? perhaps you execute a query somewhere which alters an entity in the db. You won't get a signal back some record has been altered by a multi-row update statement. That's the point: if you consider your app stateless, you don't have these problems. However if you try to make it statefull, it will result in a lot of problems which all relate to the stateless nature of webapps.

Frans Bouma | Lead developer LLBLGen Pro
netLearner
User
Posts: 150
Joined: 18-Oct-2003
# Posted on: 21-Jan-2005 16:12:11   

As soon as the user logs in I save the User object into a session Variable. Sometime later the user might decide to change his FirstName. Since there is no IdentityMap, its very possible that a new Instance of the user could be created. The FirstName is modified and then saved. However now the copy of the User object stored in the session variable is now out of sync with the DataBase.

Kulki

Here's what i think, I don't know what exactly IdentityMap does but, When a user changes his first name instead of creating a new user instance you could just refer back to the user instance in session and modify it and save it. It will be then be in sync with the data in DB.

kulki
User
Posts: 26
Joined: 20-Dec-2004
# Posted on: 21-Jan-2005 16:59:54   

Otis wrote:

With an identity map you won't be helped either: what if your app runs in a webfarm scenario?

I am aware that in a web farm scenario Identity Maps won't work, but for my current project I won't need any web farms. Can I then implement a Identity Map then?

Otis wrote:

How can it know something has changed? perhaps you execute a query somewhere which alters an entity in the db. You won't get a signal back some record has been altered by a multi-row update statement. That's the point: if you consider your app stateless, you don't have these problems. However if you try to make it statefull, it will result in a lot of problems which all relate to the stateless nature of webapps.

Are you then suggesting that we make out web app completely stateless? It could be done I suppose but thats a lot of work and we end up making a lot of DB calls. I suppose there is no harm in keeping readonly data in the sessions and Cache. In your experience whats typically done for web based apps? Stateless or stateful?

kulki
User
Posts: 26
Joined: 20-Dec-2004
# Posted on: 21-Jan-2005 17:14:36   

Otis wrote:

With an identity map you won't be helped either: what if your app runs in a webfarm scenario?

What you should do is to give an entity a uniquely identifying attribute, a PK, and one which is not easily changed, for example an artificial ID. Firstname + Lastname is not good enough. In your scenario, the new user is saved when its created. When he changes his name attribute, that's ok, save it again. If another entity with the same data is created, it's another entity, and you should check when you're creating THAT entity if it is a duplicate or not.

I always use a Guid as a PK. I want to check for duplicate objects when its being created. How I am supposed to implement something like this? I thought this was the reason why Identity Maps existed. I really wanna implement some sort of an Identity Map which might only work for my needs and may not be generic enough to solve all problems. I am building a Web based app which will NOT use web farms. I plan to use .NET remoting. I am trying to understand exatly where the Identity Map should be located, should it be on the client or the server. I think it ought to be on the client side.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 21-Jan-2005 17:33:49   

An identity map is an in-memory list of existing keys. This means that you can consult the list if some key exist, also via the identity map you could read back an entity with a known key.

As these things fall on their face in some situations I'ven't implement them.

However, if you want to check if something exists, use a scalar query simple_smile . You then of course run the risk of having an insert between the scalar query and the insert of your data, but you can catch that with an exception and report then an error to the user.

You can create a simple identity map on the SERVER using a hashtable. Never do this on the client as 2 clients connecting your service don't see eachother and will soon have maps which are outofsync.

But i'd go for a scalar query. if the scalar query returns a value, the value is taken and inserting another one will result in a duplicate.

Frans Bouma | Lead developer LLBLGen Pro
JimFoye avatar
JimFoye
User
Posts: 656
Joined: 22-Jun-2004
# Posted on: 21-Feb-2005 05:14:22   

Otis wrote:

Commit() is done on the server, I think, as the GUI should call a server method and pass the UnitOfWork object.

In distributed environments, you work disconnected, that's the key: so you think in these steps: 1) create containers (entity objects) 2) add data to/load data in containers (from server for example) 3) show data in modifiers (forms) 4) data is modified and collected for persistence 5) collected data is send to server for persistence 6) process is ended

At stage 6) the state should be considered void. It's up to you to ignore that and keep data around on the client. But as you work disconnected, there is no feedback from the server for example if you send an entity from client to server and it is saved there: you won't all of a sudden have an outofsync entity on the client, as that's just a copy of the object on the server. So if you want to keep on working on the client with the data, you have to consider that after step 6 you have to rewind to 1) or 2), unless you know what you can keep (read-only data for example).

If you're in 6) and you rewind to 4), you're modifying data which is out of sync with the server. LLBLGen Pro doesn't provide you with a layer which takes care of that, as I believe you should control that yourself, because only then the developer has full control over when what happens. So when you send a UoW to the server, you have to realize you're in 5) moving to 6) and it's all over for that process. If that's not the case, then you shouldn't move from 4) to 5) there, but wait and persist the data later.

I just got this out of synch error tonight and was poking around the forum when I found this. Excellent explanation! I understand now I have to refetch my entities if I want to keep using them.

Now, get this into the manual!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 21-Feb-2005 09:14:45   

Yes sir! wink

Frans Bouma | Lead developer LLBLGen Pro