views:

405

answers:

1

I am trying to rearchitecture a program which runs on Win CE 5.0 devices, using Compact Framework. Right now the application communicates directly with the database, pulling down data, making changes, and sending those back to the database. Each client is responsible for retrieving updates via polling the database.

I want to develop something more client/server oriented, where clients are bound to a server, receive data, send changes to the server which in turn propagates those changes to the other bound clients - something approaching real-time. I was looking at WCF and duplex binding, but it seems as if those capabilities are limited in .Net CF.

Any suggestions (and examples) would be greatly appreciated.

+1  A: 

An architecture I've used for many Windows-Mobile-clients-to-central-server applications is to mediate all client-to-central-database communications through a .Net web service application. Generally, the web service has methods that get data from the database and return it in a DataSet. The client app works with this DataSet (displaying and adding, updating and/or deleting records) and then passes the modified DataSet back to a web service method that persists any changes back into the main database (the DataSet has many convenient built-in methods that make this easy, like GetChanges(), for example).

If the client app does not have regular connectivity to the web service, it's relatively easy to also enable persisting of the data in a local database (SqlCE is an excellent choice for this), although your client app will be significantly simpler if you don't have to do this. Either way, it's very handy to design your central database to use GUIDs (aka uniqueidentifier in SQL Server) as primary keys, and create the keys on the client side whenever new data is added.

Having the changes submitted from one client sent automagically to all the other clients is a more difficult situation. The best way to do this is really dependent upon what kind of connectivity your WinCE devices have with the web service. If the devices are essentially always connected, you can have each device essentially "register" themselves with a web service method whenever they start, and the web service then maintains a static list of registered client instances. Whenever changes come in from one client, the web service can "push" these changes out to each registered client.

If the devices are only connected intermittently (like in every app of this type I've ever written), it's best to stick with the polling concept, and have each client app "check in" with the web service (every minute or every 30 seconds or whatever) and update itself with any pending changes. In practice, this approach is nearly indistinguishable from a "push" architecture anyway, and is easier to implement and more reliable in practice.

MusiGenesis
These clients are always connected. I like the idea of clients registering and pushing updates out to them. I'm struggling to find an example of how to implement this.
Josh
@Josh: what you want to do is a variant of calling web services ansynchronously. Here is a decent tutorial on the subject: http://ondotnet.com/pub/a/dotnet/2005/08/01/async_webservices.html
MusiGenesis
Basically, the "registering" process is just the client making a call to a web service method and passing in an AsyncCallback, which is just a delegate to a method that "lives" in the client application. On the server side, you maintain these callbacks from clients in a static collection (List<AsyncCallback>). Whenever the server needs to "push" something out to all clients, the server-side method iterates through the collection of callbacks and either sends the necessary data to the callbacks, or else just sends a small message to each client ...
MusiGenesis
... and the client then makes a synchronous web service call to retrieve the new data (this is how I'd do it). In the server-side method, whenever you call the client's callback an exception will be thrown (I forget what kind) if the client has been disconnected since it registered.
MusiGenesis
This possibility of the client's disconnecting after registering is why the asynchronous/push architecture just isn't worth the effort, in my opinion, because you have to deal on the server side with keeping track of whether each client has properly received each relevant notification or not. Morever, even if the server "knows" a client got a particular notice, you can't really ever know whether the client processed it properly or not.
MusiGenesis
In my opinion, it's a lot easier to keep the logic of what the client has to do in the client application itself, and to keep the web service "dumb", meaning that it never does anything but respond to client requests whenever it receives them. This also lets you keep all your web service methods stateless, since maintaining state in a web service is kind of a pain in the butt, especially since web services usually shut down after 20 idle minutes.
MusiGenesis
Thanks a lot - you've given me a lot to think about.
Josh
@Josh: you're welcome. You can thank me by upvoting this answer: http://stackoverflow.com/questions/297037/what-tricks-do-you-use-to-get-yourself-in-the-zone/297090#297090
MusiGenesis
I'm whoring myself out for another gold badge. :)
MusiGenesis
already did. ;-)
Josh