Tuesday, September 24, 2013

Silverlight RIA service, DomainContextBatchLoader

I am working on Silverlight these days. And we are using Silverlight RIA service and Entity framework to access database.

If you had ever worked with RIA , you will come across a situation that you might want to load many entities from the server using different queries, before you can present an appropriate UI to your customer.

for example, customer, you might want to load customer detail infomation, customer history, customer order etc etc.

I did some search , and didn't find an appropriate batch loader, so create one by myself, in case someone else also need to implement similar features, can take it as a reference.

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
namespace SilverlightApplication4
{
    public class DomainContextBatchLoader
    {
        public abstract class LoadStep
        {
            public bool IsComplete { getset; }
            public abstract void Execute();
            public Action<LoadOperation> OnSuccess;
            public Action<LoadOperation> OnFail;
        }
 
        public class BatchLoadStep<T> : LoadStep
            where T : Entity
        {
            private DomainContext _context;
            public EntityQuery<T> EntityQuery { getset; }
            private LoadBehavior _loadBehavior = LoadBehavior.MergeIntoCurrent;
 
            #region Construction
            public BatchLoadStep(DomainContext contextEntityQuery<T> queryLoadBehavior loadBehavior = LoadBehavior.MergeIntoCurrent)
            {
                _context = context;
                EntityQuery = query;
                _loadBehavior = loadBehavior;
            }
            #endregion
            #region Overrides
            public override void Execute()
            {
                _context.Load(EntityQuery_loadBehaviorlp =>
                {
                    this.IsComplete = true;
                    this.LoadOperation = lp;
                    if (lp.IsComplete && !lp.HasError)
                    {
                        if (this.OnSuccess != null)
                        {
                            this.OnSuccess(lp);
                        }
                    }
                    else
                    {
                        if (this.OnFail != null)
                        {
                            this.OnFail(lp);
                        }
                    }
                }, null);
            }
            #endregion
 
            public LoadOperation<T> LoadOperation { getset; }
        }
 
        #region Construction
        public DomainContextBatchLoader(Action<DomainContextBatchLoader> completeAction)
        {
            this._completeAction = completeAction;
        }
        #endregion
 
        #region Private Properties
        private Action<DomainContextBatchLoader> _completeAction = null;
        private List<LoadStep> _lstSteps = new List<LoadStep>();
        private List<LoadOperation> _lstFaildOperation = new List<LoadOperation>();
        public event EventHandler OnComplete;
        #endregion
 
        #region Methods
        public void Add<T>(DomainContext contextEntityQuery<T> queryLoadBehavior loadBehaviorwhere T : Entity
        {
            var step = new BatchLoadStep<T>(contextqueryloadBehavior);
            step.OnSuccess = lp =>
            {
                this.CheckComplete();
            };
            step.OnFail = lp =>
            {
                this._lstFaildOperation.Add(lp);
                this.CheckComplete();
            };
            _lstSteps.Add(step);
        }
        private void CheckComplete()
        {
            if (!this._lstSteps.Any(o => o.IsComplete == false))
            {
                if (this._completeAction != null)
                {
                    this._completeAction(this);
                }
                if (this.OnComplete != null)
                {
                    this.OnComplete(thisnew EventArgs());
                }
            }
        }
        public void Start()
        {
            if (_lstSteps.Count > 0)
                _lstSteps.ForEach(o => o.Execute());
            else
            {
                CheckComplete();
            }
        }
 
        public IEnumerable<T> GetEntities<T>() where T : Entity
        {
            var step = _lstSteps.OfType<BatchLoadStep<T>>().FirstOrDefault();
            if (step != null)
                return step.LoadOperation.Entities.OfType<T>();
            return null;
 
        }
        public int FailedOperationCount { get { return _lstFaildOperation.Count; } }
 
        public IEnumerable<LoadOperation> FailedOperations
        {
            get { return _lstFaildOperation; }
        }
        #endregion
    }
}

No comments:

Post a Comment