This is a migrated thread and some comments may be shown as answers.

OpenAccessContextBase.Refresh() does not fire instance's INotifyPropertyChanged.PropertyChanged event

5 Answers 81 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Widodo
Top achievements
Rank 1
Widodo asked on 15 Sep 2012, 04:10 AM
Hi, 

I'm evaluating OpenAccess as ORM backend for my application.
I'm developing WPF application with large amount of long running thread.
As i read in this thread, I understand that it is preferred for each thread to have it's own context.
I have enabled the L2 cache as well.

I have successfully perform update from thread A and read the change from thread B using the context Refresh() method. Unfortunately, the refresh method doesn't raise the PropertyChanged event, so my View doesn't reflect the latest data.

Here is my simplified example code:

// Get the context of the main thread
var mainContext = ContextManager.GetContext(Thread.CurrentThread.ManagedThreadId);
 
Person personMain = mainContext.Persons.Single(p => p.Id == 1);
personMain.Name = "Old Name";
mainContext.SaveChanges();
 
Task.Factory.StartNew(() =>
{
    // Get the context of the new thread.
    var threadContext = ContextManager.GetContext(Thread.CurrentThread.ManagedThreadId);
 
    Person personThread = threadContext.Persons.Single(p => p.Id == 1);
    personThread.Name = "New Name";
    threadContext.SaveChanges();
 
    // At this point, personMain.Name value is "Old Name".
    // Now refresh the person instance of the main thread.
    mainContext.Refresh(RefreshMode.OverwriteChangesFromStore, personMain);
    // At this point, personMain.Name value is correctly changed to "New Name",
    // but personMain.PropertyChanged event is not fired.
});

I can avoid the PropertyChanged issue by sharing the main thread's context to other threads, but I'm afraid it will introduce other concurency problem. My application will have hundreds of long running threads during its lifecycle. Sharing a context for hundreds thread means share a transaction over hundres threads, and I think this is not good solution.

Did I miss something, or is there any better solution for my case?

Thanks,
Widodo

5 Answers, 1 is accepted

Sort by
0
Widodo
Top achievements
Rank 1
answered on 15 Sep 2012, 08:04 AM
Hi,

I forgot to mention that the Person class in the example above implements INotifyPropertyChanged.
The PropertyChanged event is fired correctly when the object is updated within the main thread. The issue comes if I update the object from another thread as I described above.

Regards,
Widodo
0
PetarP
Telerik team
answered on 19 Sep 2012, 02:42 PM
Hi Widodo,

 You have not missed anything. During refresh the new values (the one that are retrieved from the database) are actually obtained from our internal state object - thus the properties setter is not called and you are not getting your event fired.
The only possible solution different than the one you suggested is to subscribe to the Refreshed event and handle the notification there. You can find the Refreshed even on context level in the Event property.

All the best,
Petar
the Telerik team
Follow @OpenAccessORM Twitter channel to be the first one to get the latest updates on new releases, tips and tricks and sneak peeks at our product labs!
0
Widodo
Top achievements
Rank 1
answered on 20 Sep 2012, 10:13 AM
Hi Petar,

Thanks for pointing me to context Refreshed event.
I just realize that there are some useful events in the context.

However, I expect the PropertyChanged event is fired since I bind the object to WPF control.
Since it is by designed that the PropertyChanged is not fired during Refresh() calling, then it is not OpenAccess issue.  It is my task to force-rebind the control then.
I thought it is common issue in WPF on how to force refresh the binding, but I have spent for a while on Google with no luck. I think I need a more deep search regarding this issue.

I would appreciate if anyone can point me to the right direction.

Thanks,
Widodo
0
PetarP
Telerik team
answered on 25 Sep 2012, 09:45 AM
Hi Widodo,

 In order to update a wpf UI element explicitly you will need to obtain the binding expression for that element. Once you do that you will be able to either update the source (the property) or the target (the UI element).
For example if we have a text box that is bound to a string property that does not implement the INotifyPropertyChanged interface we can update it in the following manner:

var bindingExpression = sampleTextBox.GetBindingExpression(TextBlock.TextProperty);
bindingExpression.UpdateTarget();
This code can be placed in the event handler of the Refreshed context event so that your UI is updated accordingly.
I hope that helps.

All the best,
Petar
the Telerik team
Follow @OpenAccessORM Twitter channel to be the first one to get the latest updates on new releases, tips and tricks and sneak peeks at our product labs!
0
Widodo
Top achievements
Rank 1
answered on 25 Sep 2012, 03:04 PM
Thanks Petar,

That's very helpful.

Regards,
Widodo
Tags
General Discussions
Asked by
Widodo
Top achievements
Rank 1
Answers by
Widodo
Top achievements
Rank 1
PetarP
Telerik team
Share this question
or