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

6 posts, 0 answers
  1. Widodo
    Widodo avatar
    4 posts
    Member since:
    Apr 2012

    Posted 14 Sep 2012 Link to this post

    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
  2. Widodo
    Widodo avatar
    4 posts
    Member since:
    Apr 2012

    Posted 15 Sep 2012 Link to this post

    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
  3. DevCraft banner
  4. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 19 Sep 2012 Link to this post

    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!
  5. Widodo
    Widodo avatar
    4 posts
    Member since:
    Apr 2012

    Posted 20 Sep 2012 Link to this post

    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
  6. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 25 Sep 2012 Link to this post

    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!
  7. Widodo
    Widodo avatar
    4 posts
    Member since:
    Apr 2012

    Posted 25 Sep 2012 Link to this post

    Thanks Petar,

    That's very helpful.

    Regards,
    Widodo
Back to Top
DevCraft banner