Monday, May 16, 2005

[Opf3] Using multiple storages and web services

I got the following question sent today. I was thinking that this could interest also other people:


Is it possible using Opf3 to do the following scenario.

On a web server
Retrieve data from SQL server and send data to client via web service.
On the client
Persist the data retrieved from the server to say VistaDB db, with a few more fields added?


Answer:

Yes, it is possible. You can load data from one storage and persist it to another storage. The following post shows how to do that:
http://christianliensberger.blogspot.com/2005/05/opf3-using-multiple-storages.html.

You have only to think about a few more things since you are sending the object via a web service. It is recommended to implement the ISelfContainingObject when remoting an object or loading an object and then persisting it with another instance of the ObjectContext. This has to be done because without implementing the interface an object is coupled to the instance of the ObjectContext that is used to load it. The ObjectContext manages internally the status of the object (has the object been loaded, deleted etc.). This works fine when you are using one instance of the ObjectContext within your application or you are loading all objects with the same instance of the ObjectContext that is used to save the changes.

When you implement the ISelfContainingObject interface the object itself manages the status and holds its concurrency data. This scenario works fine when you use different instances of the ObjectContext which are bound to the same database (storage) or remote the object and save it in the end by using an instance of the ObjectContext that uses the same database as the one that loaded it.

In your case you have two different databases. When you implement this interface (ISelfContainingObject) you have to reset the status of the object manually. This is done by the following piece of code:


// Reset the state of the object.
((ISelfContainingObject)obj).ObjectInfo.ObjectState = ObjectStates.None;


Now Opf3 thinks that the object hasn’t been loaded from any storage and you can safely store it (Opf3 does an insert). When you are not implementing the ISelfContainingObject interface you have no problems in this specific scenario. The ObjectContext (you used to load the object) holds internally the status of the object and the other instance does not care about that status and treats the object as if it would be a new one (= insert to the storage).

But you have problems when you load an object, remote it using remoting or web services and try to save it to an instance of the ObjectContext that is bound to the same database that you used to load the object from. Without implementing the ISelfContaining interface once the object left the current AppDomain the ObjectContext removes the status and concurrency data. The ObjectContext “thinks” that the object has been destroyed (he can’t reach it anymore). When the object returns to the AppDomain and is also saved with the same instance of the ObjectContext (used to load it) the status data can’t be found anymore (= insert to the storage).

For your scenario I would recommend implementing the ISelfContainingObject interface and reset the ObjectState. It’s a clean way and you have no problems afterwards when using the persistent object in your application. If you use the persistent object only to do a copy from the old database (or for doing an import) you don’t need to implement the interface as long as you don’t remote the objects afterwards and you save the objects always with the same instance of the ObjectContext you used also to load them.

0 Comments:

Post a Comment

<< Home