Using local database in WP7

Using local database in WP7

Old forum URL: forums.lhotka.net/forums/t/11196.aspx


mesh posted on Saturday, February 25, 2012

Can someone please help me with this example? I cant find any example on accessing local database in SL/WP7 and CSLA.
    public static void GetExistingProject(int projectId, EventHandler<DataPortalResult<ProjectGetter>> callback)
    {
      DataPortal.BeginFetch<ProjectGetter>(new Criteria { ProjectId = projectId, GetRoles = !RoleList.IsCached }, (o, e) =>
      {
        if (e.Error != null)
          throw e.Error;
        if (!RoleList.IsCached)
          RoleList.SetCache(e.Object.RoleList);
        callback(o, e);
      });
    }
#if !SILVERLIGHT
    private void DataPortal_Fetch(Criteria criteria)
    {
      if (criteria.ProjectId == -1)
        Project = ProjectEdit.NewProject();
      else
        Project = ProjectEdit.GetProject(criteria.ProjectId);
      if (criteria.GetRoles)
        RoleList = RoleList.GetList();
    }
#endif
1) How can I write DataPortal_Fetch method for Windows Phone? This is a bad solution, right? This way  I am blocking main thread?
#if WINDOWS_PHONE
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public void DataPortal_Fetch(Criteria criteria, Csla.DataPortalClient.LocalProxy<ProjectGetter>.CompletedHandler handler)
    {
        try
        {
            var sync = new AutoResetEvent(false);
            if (criteria.ProjectId == -1)
                Project = ProjectEdit.NewProject();
            else
            {
                Project = ProjectEdit.GetProject(criteria.ProjectId, (o, e) =>
                {
                    if (e.Error != null)
                        throw e.Error;
                    Project = e.Object;
                    sync.Set();
                });
                sync.WaitOne();
            }
            if (criteria.GetRoles)
            {
                RoleList = RoleList.GetList((o, e) =>
                {
                    if (e.Error != null)
                        throw e.Error;
                    RoleList = e.Object;
                    sync.Set();
                });
                sync.WaitOne();
            }
            handler(this, null);
        }
        catch (Exception ex)
        {
            handler(null, ex);
        }
    }
#endif
2) Is this any better solution?
    private bool ProjectLoaded = false;
    private bool RoleListLoaded = false;
#if WINDOWS_PHONE
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public void DataPortal_Fetch(Criteria criteria, Csla.DataPortalClient.LocalProxy<ProjectGetter>.CompletedHandler handler)
    {
        try
        {
            if (criteria.ProjectId == -1)
            {
                Project = ProjectEdit.NewProject();
                ProjectLoaded = true;
            }
            else
            {
                Project = ProjectEdit.GetProject(criteria.ProjectId, (o, e) =>
                {
                    if (e.Error != null)
                        throw e.Error;
                    Project = e.Object;
                    ProjectLoaded = true;
                    if (RoleListLoaded || !criteria.GetRoles) handler(this, null);
                });
            }
            if (criteria.GetRoles)
            {
                RoleList = RoleList.GetList((o, e) =>
                {
                    if (e.Error != null)
                        throw e.Error;
                    RoleList = e.Object;
                    RoleListLoaded = true;
                    if (ProjectLoaded) handler(this, null);
                });
            }
            if (ProjectLoaded && (RoleListLoaded || !criteria.GetRoles)) handler(this, null);
        }
        catch (Exception ex)
        {
            handler(null, ex);
        }
    }
#endif
 
3) what is the best way to invoke CompletedHandler AFTER all async calls are finished?
4) Is it ok to call async DataPortal methods in ProjectEdit.GetProject and RoleList.GetListon ( on "logical server side" )?
5) Same "problem" would be if I try multiple async calls to a web service ( SOA ) and then invoking CompletedHandler after all calls are finished.
6) Another solution for this example would be calling DAL directly and using Child_Fetch() to load data?
Thanks,

RockfordLhotka replied on Saturday, February 25, 2012

I don't have time to write the code for you right now.

But here's the thing you really need to understand: the "asynchronous" data portal isn't actually asynchronous at all. It is async-enabled. If YOU don't make any async calls in your DataPortal_Fetch method, nothing is async.

As I said in the other thread, this means that you can directly interact with the local database in your DataPortal_Fetch method as long as you call the handler when you are done. Nothing will be async in that case.

My recommendation is to use the same UOW pattern I show in the Using CSLA 4: Windows Phone book and make the unit of work object's DataPortal_Fetch use a BackgroundWorker from Csla.Threading so you don't block the user (because that would be bad). This is where you introduce actual async behavior.

In the DoWork event handler for the BackgroundWorker is where you will fetch the two root objects you need. THOSE objects will have DataPortal_Fetch methods that DO NOT do any async work at all. They'll directly interact with the local database, calling handler when they are done.

The code in the UOW class's DoWork event handler for the BackgroundWorker will call the "async" factory methods for the two root objects. But those methods won't really be async, so the callbacks will occur synchronously, allowing the DoWork code to be very simple - no worries about thread blocking or anything, because the thread will be blocked.

Copyright (c) Marimer LLC