I'm fairly new to MVVM, so please excuse me if this problem has a well-known solution.
We are building a bunch of model classes which have some core properties that are loaded up-front, as well as some additional properties which could be lazy-loaded on demand by making a web API call (update: to clarify, it would be a web API call per lazily-loaded property).
Rather than having multiple models, it seems sensible to have a single model with the lazy-loading logic in there. However, it also seems that the lazy-loaded properties should not block when accessed, so that when the View binds to the ViewModel and it binds to the Model, we don't block the UI thread.
As such, I was thinking of a pattern something along the lines of when a lazy property on the Model is accessed it begins an asynchronous fetch and then immediately returns a default value (e.g. null). When the asynchronous fetch is complete, it will raise a PropertyChanged event so that the ViewModel/View can re-bind to the fetched value.
I've tried this out and it seems to work quite nicely, but was wondering:
Are there any pitfalls to this approach that I haven't found out about yet, but will run into as the app increases in complexity?
Is there an existing solution to this problem either built into the framework, or which is widely used as part of a 3rd party framework?
I did something like this in the past and the one thing I kept forgetting about is you can't call your async property through any kind of code behind and expect it to have a value.
So if I lazy-load a list of Customer.Products, I can't reference Customer.Products.Count in the code-behind because the first time it's called the value is NULL or 0 (depending on if I create a blank collection or not)
Other than that, it worked great for the bindings. I was using the Async CTP library for making my async calls, which I found was absolutely wonderful for something like this.
public ObservableCollection<Products> Products
{
get
{
if (_products == null)
LoadProductsAsync();
return _products;
}
set { ... }
}
private async void LoadProductsAsync()
{
Products = await DAL.LoadProducts(CustomerId);
}
Update
I remember another thing I had issues with was data that actually was NULL. If Customer.Products actually returned a NULL value from the server, I needed to know that the async method had run correctly and that the actual value was null so that it didn't re-run the async method.
I also didn't want the async method to get run twice if someone called the Get method a 2nd time before the first async call had completed.
I solved this at the time by having an Is[AsyncPropertyName]Loading/ed property for every async property and setting it to true during the first async call, but I wasn't really happy about having to create an extra property for all async properties.
Related
Say,there is a requirement that a customer object is loaded from the db to a silverlight application, so that the customer details are shown in the UI. We need to detect if the user is changing any data in the UI.
We are listening to property changed notifications from the view model. However, when the notifications are result of property change as part of the loading process we have to discard it.
class CustomerLoader
{
Helper helerobj;
Address addressobj;
Profile profileobj;
void LoadFromDb()
{
helperobj.Load();
addressobj.Load();
profileobj.Load();
//start listening after the loading finished
this.propertychanged += new PropertyChangedEventHandler(handlepropertychanged);
}
The trouble with this is the inner objects might be calling asynchronous functions which might set properties. So by the time we started the property change listening, the loading might not have been finished.
We need to know when the loading is actually done. As of now we are asking the developers who are developing the inner object classes to accept a callback in the parameter which they should call when the function is finished.
Is there any other way to do it?
You want nothing but a really classic asynchronous objet loading.
So yes, the only solution is to ask developers working on the loading to propose an asynchronous function. Now you hav several solution to achieve asynchronicity in Silverlight.
You could either provide a callback as you do, or use async and await to manage your asynch task as explain here: http://10rem.net/blog/2012/05/22/using-async-and-await-in-silverlight-5-and-net-4-in-visual-studio-11-with-the-async-targeting-pack
I read in the backbone documentation that calling collection.reset() clears the collection. I want to know if it removes the models as well or do they continue to live in memory?
If they're not removed is there an easier way to remove all the models in a collection without iterating through the models and calling model.remove()?
You could listen for the reset event from the model and do your cleanup and this.destroy() in response. That's what the event hooks are for. See http://backbonejs.org/#Events-catalog
Note: You absolutely should not change or override any method or property prefixed by an underscore, such as _removeReference. The underscores mean that it is intended as an internal method or property, and that the internal implementations may change (their API's are considered unstable). Upgrading Backbone could break any code that relies on underscore-prefixed methods, even if the release is advertised as a backwards-compatible change.
I know your question says "without iterating", but it really is the most reliable way of handling this. Consider a case where a model has been moved from one collection to another, but it's still listening on the first collection's reset event (because a programmer six months later didn't notice the connection).
Now when the first collection gets reset, the moved model gets destroyed. Oops!
Iterating over the collection probably is the best way to handle this if you don't have an endpoint on your API that will delete all objects in a collection in batch on the API server (which is often how this is handled).
Luckily, that iteration is pretty easy:
destroyAll: function () {
var promises = [];
while(this.models.length > 0) {
promises.push( this.models[0].destroy() );
}
// handle errors communicating with the server
$.when(promises).fail(function (response) {
this.trigger('syncError',
response);
}.bind(this));
}
What you are looking for is, probably, for the models to be garbage-collected. That is, that nobody has a reference to these models anymore, after they are removed from the collection.
Backbone does its part of removing the references that it set on the models, when they are removed from the collection. However, you have to do your own cleanup if your code has references to those models. Most of the time, this happens if those models are registered as event listeners, like in this example: http://jsfiddle.net/dira/4uxp4/2/
Taking a look at the implementation of reset, you could change _removeReference to call a cleanup function on the model as well. And in the model, remove the model from all the listeners/all the other objects that keep a reference to it.
I am using WCF services asynchronously in a WPF application. So I have class with all the web service. The view models call the method in this proc, which in-turn calls the web service.
So the view Model code looks like this:
WebServiceAgent.GetProductByID(SelectedProductID, (s, e)=>{States = e.Result;});
And the WebService agent looks like:
public static void GetProductByID(int ProductID, EventHandler<GetProductListCompletedEventArgs> callback)
{
Client.GetProductByIDCompleted += callback;
Client.GetProductByIDAsync(ProductID);
}
Is this a good approach? I am using MVVM light toolkit. So the View Model static, so in the lifetime of the application, the view model stays. But each time the view model calls this WebServiceAgent, I think I am registering an event. But that event is not being unregistered.
Is this a problem. Lets say the view Model is called for 20 - 30 times. I am inserting some kind of memory leak?
Some helpful information, based on the mistakes I learned from myself:
The Client object seems to be re-used all the time. When not unregisering event handlers, they will stack up when future invokations of the same operations finish and you'll get unpredictable results.
The States = e.Result statement is executed on the event handler's thread, which is not the UI dispatcher thread. When updating lists or complex properties this will cause problems.
In general not unregistering event handlers when they are invoked is a bad idea as it will indeed cause hard to find memory leaks.
You should probably refactor to create or re-use a clean client, wrap the viewmodel callback inside another callback that will take care of unregistering itself, cleaning up the client, and invoking the viewmodel's callback on the main dispatcher thread.
If you think all this is tedious, check out http://blogs.msdn.com/b/csharpfaq/archive/2010/10/28/async.aspx and http://msdn.microsoft.com/en-us/vstudio/async.aspx. In the next version of C# an async keyword will be introduced to make this all easier. A CTP is available already.
Event handlers are death traps and you will leak them if you do not "unsubscribe" with "-=".
One way to avoid is to use RX (Reactive Extensions) that will manage your event subscriptions. Take a look at http://msdn.microsoft.com/en-us/data/gg577609 and specifically creating Observable by using Observable.FromEvent or FromAsync http://rxwiki.wikidot.com/101samples.
This is unfortunaltely not a good approach.
I learned this the hard way in silverlight.
Your WebserviceAgent is probably a long-life object, whereas the model or view is probably short-life
Events give references, and in this case the webservice agent, and wcf client a reference to the model. A long lifeobject has a reference to a short life object, this means the short life object will not be collected, and so will have a memory leak.
As Pieter-Bias said, the async functionality will make this easier.
Have you looked at RIA services? This is the exact problem that RIA services was designed to solve
Yes, the event handlers are basically going to cause a leak unless removed. To get the near-single line equivalent of what you're expressing in your code, and to remove handlers you're going to need an instance of some sort of class that represents the full lifecycle of the call and does some housekeeping.
What I've done is create a Caller<TResult> class that uses an underlying WCF client proxy following this basic pattern:
create a Caller instance around an existing or new client proxy (the proxy's lifecycle is outside of the scope of the call to be made (so you can use a new short-lived one or an existing long-lived one).
use one of Caller's various CallAsync<TArg [,...]> overloads to specify the async method to call and the intended callback to call upon completion. This method will choose the async method that also takes a state parameter. The state parameter will be the Caller instance itself.
I say intended because the real handler that will be wired up will do a bit more housekeeping. The real callback is what will be called at the end of the async call, and will
check that ReferenceEquals(e.UserState, this) in your real handler
if not true, immediately return (the event was not intended to be the result of this particular call and should be ignored; this is very important if your proxy is long lived)
otherwise, immediately remove the real handler
call your intended, actual callback with e.Result
Modify Caller's real handler as needed to execute the intended callback on the right thread (more important for WPF than Silverlight)
The above implementation should also have separate handlers for cases where e.Error is non-null or e.Cancelled is true. This gives you the advantage of not checking these cases in your intended callback. Perhaps your overloads take in optional handlers for those cases.
At any rate, you end up cleaning up handlers aggressively at the expense of some per-call wiring. It's a bit expensive per-call, but with proper optimization ends up being far less expensive than the over-the-wire WCF call anyway.
Here's an example of a call using the class (you'll note I use method groups in many cases to increase the readability, though HandleStuff could have been result => use result ). The first method group is important, because CallAsync gets the owner of that delegate (i.e. the service instance), which is needed to call the method; alternatively the service could be passed in as a separate parameter).
Caller<AnalysisResult>.CallAsync(
// line below could also be longLivedAnalyzer.AnalyzeSomeThingsAsync
new AnalyzerServiceClient().AnalyzeSomeThingsAsync,
listOfStuff,
HandleAnalyzedStuff,
// optional handlers for error or cancelled would go here
onFailure:TellUserWhatWentWrong);
I have often times wondered about it but now that I have encountered a piece of logic that incorporates it, I thought I should go ahead and get some help on deciphering the fundamentals. The problem is as follows, I am looking at a WPF application that is utilizing the Composite Application Library. Within the source of the application I came across the following line of code in the Presentation of a view. For the sake of convinience I will call it Presentation A:
private void OnSomethingChanged(SomeArgumentType arguement)
{
UnityImplementation.EventAggregator.GetEvent<EventA>().Publish(null);
}
When I saw the method Publish in the above given method, my gut told me there must be a Subscribe somewhere and in another class, I will call it Presentation B there was the following:
UnityImplementation.EventAggregator.GetEvent(Of EventA).Subscribe(AddressOf OnSomeEventA)
There was a private function in the same class called OnSomeEventA that had some logic in it.
My question here is that how is everything wired over here? What exactly is achieved by the 'Publish' 'Subscribe' here? When 'something' changes, how does the compiler know it has to follow the logic in OnSomethingChanged that will 'Publish' an event that is 'Subscribed' by another class where the logic of the event handler has been described? It will be great to understand the underlying wiring of this process.
Thanks
The first time GetEvent<T> is called for each event (identified by the type parameter T) the EventAggregator creates an empty list of methods to call when that event is published. Typically, this will happen immediately before the first call to Publish or Subscribe (as in your examples).
Then:
Whenever Subscribe is called a method is added to the list.
Whenever Publish is called it walks through the list and makes those calls.
So, the call to Publish() in Presentation A results in all of the methods that have been registered by calling Subscribe being called, which in your example would include Presentation B's OnSomeEventA method.
Try setting a breakpoint in the OnSomeEventA method and take a look at the stack, and don't forget the source is available, too!
Currently for ASP.Net stuff I use a request model where a context is created per request (Only when needed) and is disposed of at the end of that request. I've found this to be a good balance between not having to do the old Using per query model and not having a context around forever. Now the problem is that in WPF, I don't know of anything that could be used like the request model. Right now it looks like its to keep the same context forever (Which can be a nightmare) or go back to the annoying Using per query model that is a huge pain. I haven't seen a good answer on this yet.
My first thought was to have an Open and Close (Or whatever name) situation where the top level method being called (Say an event handling method like Something_Click) would "open" the context and "close" it at the end. Since I don't have anything on the UI project aware of the context (All queries are contained in methods on partial classes that "extend" the generated entity classes effectively creating a pseudo layer between the entities and the UI), this seems like it would make the entity layer dependent on the UI layer.
Really at a loss since I'm not hugely familiar with state programming.
Addition:
I've read up on using threads, but the
problem I have with a context just
sitting around is error and recovery.
Say I have a form that updates user
information and there's an error. The
user form will now display the changes
to the user object in the context
which is good since it makes a better
user experience not to have to retype
all the changes.
Now what if the user decides to go to
another form. Those changes are still
in the context. At this point I'm
stuck with either an incorrect User
object in the context or I have to get
the UI to tell the Context to reset
that user. I suppose that's not
horrible (A reload method on the user
class?) but I don't know if that
really solves the issue.
Have you thought about trying a unit of work? I had a similar issue where I essentially needed to be able to open and close a context without exposing my EF context. I think we're using different architectures (I'm using an IoC container and repository layer), so I have to cut up this code a bit to show it to you. I hope it helps.
First, when it comes to that "Something_Click" method, I'd have code that looked something like:
using (var unitOfWork = container.Resolve<IUnitOfWork>){
// do a bunch of stuff to multiple repositories,
// all which will share the same context from the unit of work
if (isError == false)
unitOfWork.Commit();
}
In each of my repositories, I'd have to check to see if I was in a unit of work. If I was, I'd use the unit of work's context. If not, I'd have to instantiate my own context. So in each repository, I'd have code that went something like:
if (UnitOfWork.Current != null)
{
return UnitOfWork.Current.ObjectContext;
}
else
{
return container.Resolve<Entities>();
}
So what about that UnitOfWork? Not much there. I had to cut out some comments and code, so don't take this class as working completely, but... here you go:
public class UnitOfWork : IUnitOfWork
{
private static LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("UnitOfWork");
private Entities entities;
public UnitOfWork(Entities entities)
{
this.entities = entities;
Thread.SetData(slot, this);
}
public Entities ObjectContext
{
get
{
return this.Entities;
}
}
public static IUnitOfWork Current
{
get { return (UnitOfWork)Thread.GetData(slot); }
}
public void Commit()
{
this.Entities.SaveChanges();
}
public void Dispose()
{
entities.Dispose();
Thread.SetData(slot, null);
}
}
It might take some work to factor this into your solution, but this might be an option.