This is the beta of the Silverlight persistence – I want feedback on how it works and how hard/easy it is to get along with.
Yes, I have promised this for a long time but we got caught up in STUFF and then there was more STUFF and you know how it goes…
Anyway I have spent the last couple of days wrapping the final things of the Silverlight persistence up.
The first thing that got me stumped was that Silverlight does not accept WCF-interfaces that does not follow the Async pattern (with BeginOp/EndOp). The WCF interface we had for server persistence did not follow that so it had to be changed.
The second thing that got me stumped was that even when having the Async-pattern-WCF-interface, all Silverlight applications will hang if any communication is done over a WCF channel on the Main thread.
So I had to figure out a practical way to call things on a non-MainThread-thread without getting into the total chaos of an ecospace that is read and written simultaneously from multiple threads.
I am not saying that I have “solved” every thread issue in the book with this beta – but I think that I have the strategy laid out.
The biggest challenge is Lazy Load: Lazy Load is a super function of ECO that works really well and removes a ton of work for the developer – it can be dangerous too of course – creating too many server round trips – but ECO has strategies to handle that. The problem with Lazy Load in Silverlight is that the loading cannot be done on the main thread – because the app will hang. And UI-binding cannot be done in a background thread because UI is main thread.
So Lazy Load has to go? Well yes – in Silverlight it has to go, at least on the main thread. We cannot stall a main thread operation that discovers the need for loading – if we do the app will hang for ever.
It is really easy to get things to execute on a background thread:
The code above gets a free thread from the thread pool – the thing is that we want to avoid doing stuff out of sequence so we do not want just any thread. For example we do not want a multilink to become fetched AFTER we get the result of Count – we want things to happen in sequence because they depend on each other.
Threading is best used on things that does not have dependencies – in an ecospace objects have dependencies – that is 90% of the point – sure you can have some group of objects that does not depend on some other group of objects but that will not be the normal case – and if so consider 2 ecospaces.
The Service I added to handle things in the background but still in sequence is called IAsyncSupportService. It is used like this:
The IAsyncSupportService does a couple of things:
1. Ensures that tasks are executed in the sequence they are added
2. Delays the Subscriber events that a Task will emit until the Task is done then it emits them on the Main thread
The IAsyncSupportService also has a way to sync something from a Task back to the MainThread using a method called DispatchTaskToMainThread:
Make sure your ecospace objects are fully fetched from server
The thing is that you will want to ensure that you are “fully fetched” while in the Async Task and that you leave nothing to lazy load when you are back on the main thread as your UI pulls the data for the bindings – if you do not, WCF will be used on the mainthread as soon as lazy load kicks in and the app will hang… To ensure that everything is fetched can be a chore… You can do this by calling Evaluate on the expressions you know will be fetched:
Or you can do it by navigating the associations, and attributes that your UI use with Linq or code… Still a chore…
But if you use ViewModels – Code generated – or not, with the ViewModelSLUserControl or not we will do that for you automatically – go ViewModels!
The ViewModel has a new Method called EnsureSpanFetch – you can call it yourself but it is called when you assign a Root object to a ViewModel. The one time you want to call it is when you call Refresh – there is no telling what other clients have changed so we do not know if there is new data that we will be forced to load after a Refresh:
A simple enough model:
And a ViewModel:
Add it to the silverlight form:
And some codebehind
Deploying to a server
This example has a persistence server hosted in IIS. Getting everything to work properly can be a challenge. To help you smoking issues out I recommend the IE-plugin called Web Development Helper; http://projects.nikhilk.net/WebDevHelper
This tool installs in IE and when activated it shows like this and reveal all kinds of errors like a missing clientaccesspolicy file – it is a life saver :
I have published this demo server here THE SERVER
I assign this url to the PersistenceMapperClient in the Silverlight client:
The client I published here
now the interesting thing will be when you open two or more of the clients, change data in them, update the database and then refresh the other.
The full sample code is in the latest eoc6 build demos folder SilverlightWCFPersistenceDemo.
(The persistence server uses a MemoryMapper – so it will clear when IIS swaps out my server – could have used any other persistence mapper available to eco of course but that is not what this post is about )
Read this far? Thanks! Now write some comment below: