/// <summary>
        /// Find all concrete data objects includes soft deleted in the special type sorted by Name ascendingly.
        /// </summary>
        /// <param name="type">valid concrete data type</param>
        /// <returns></returns>
        public IEnumerable<ConcreteDataObject> FindAllByType(string type)
        {
            Kit.NotNull(type, "type");

            List<ConcreteDataObject> concreteDataObjects = new List<ConcreteDataObject>();
            using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
            {
                IEnumerable<ConcreteData> entities = ctx.ConcreteDatas.Where(c => c.ApplicationId == authenticationContext.ApplicationId && c.Type == type);
                foreach (ConcreteData entity in entities)
                {
                    ConcreteDataObject concreteDataObject = new ConcreteDataObject
                    {
                        ConcreteDataId = entity.ConcreteDataId,
                        Type = entity.Type,
                        CreatedBy = entity.CreatedBy,
                        CreatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(entity.CreatedDate),
                        DeleteStatus = entity.DeleteStatus,
                        Description = entity.Description,
                        ExtensionDataTypeId = entity.ExtensionDataTypeId,
                        LastUpdatedBy = entity.LastUpdatedBy,
                        LastUpdatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(entity.LastUpdatedDate),
                        Name = entity.Name,
                        Value = entity.Value
                    };

                    concreteDataObject.ParseExtensionPropertiesFrom(entity);
                    concreteDataObjects.Add(concreteDataObject);
                }

                return concreteDataObjects;
            }
        }
        /// <summary>
        /// Get concrete data by id.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ConcreteDataObject GetById(Guid id)
        {
            ConcreteDataObject concreteDataObject = base.GetCacheObject<ConcreteDataObject>(id);

            // cannot load concrete data from cache, then try to load it from database.
            if (concreteDataObject == null)
            {
                using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                {
                    ConcreteData entity = ctx.ConcreteDatas.FirstOrDefault(c => c.ApplicationId == authenticationContext.ApplicationId && c.ConcreteDataId == id);
                    if (entity == null) return null;

                    concreteDataObject = new ConcreteDataObject
                    {
                        ConcreteDataId = entity.ConcreteDataId,
                        Type = entity.Type,
                        CreatedBy = entity.CreatedBy,
                        CreatedDate = entity.CreatedDate,
                        DeleteStatus = entity.DeleteStatus,
                        Description = entity.Description,
                        ExtensionDataTypeId = entity.ExtensionDataTypeId,
                        LastUpdatedBy = entity.LastUpdatedBy,
                        LastUpdatedDate = entity.LastUpdatedDate,
                        Name = entity.Name,
                        Value = entity.Value
                    };

                    // parse dynamic properties.
                    concreteDataObject.ParseExtensionPropertiesFrom(entity);

                    // cache the business object with UTC datetime.
                    base.AddCache(concreteDataObject.ConcreteDataId, concreteDataObject);
                }
            }

            // get the copy for timezone convertion.
            concreteDataObject = concreteDataObject.Clone();

            // convert UTC datetime into client timezone before return.
            concreteDataObject.CreatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(concreteDataObject.CreatedDate);
            concreteDataObject.LastUpdatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(concreteDataObject.LastUpdatedDate);
            return concreteDataObject;
        }
        /// <summary>
        /// Get concrete data by name.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public ConcreteDataObject GetByName(string type, string name)
        {
            Kit.NotNull(type, "type");
            Kit.NotNull(name, "name");

            using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
            {
                ConcreteData entity = (from c in ctx.ConcreteDatas
                                       where c.ApplicationId == authenticationContext.ApplicationId
                                         && c.Type == type && c.Name == name
                                       select c).FirstOrDefault();

                if (entity == null) return null;

                ConcreteDataObject concreteDataObject = new ConcreteDataObject
                {
                    ConcreteDataId = entity.ConcreteDataId,
                    Type = entity.Type,
                    CreatedBy = entity.CreatedBy,
                    CreatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(entity.CreatedDate),
                    DeleteStatus = entity.DeleteStatus,
                    Description = entity.Description,
                    ExtensionDataTypeId = entity.ExtensionDataTypeId,
                    LastUpdatedBy = entity.LastUpdatedBy,
                    LastUpdatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(entity.LastUpdatedDate),
                    Name = entity.Name,
                    Value = entity.Value
                };

                concreteDataObject.ParseExtensionPropertiesFrom(entity);
                return concreteDataObject;
            }
        }
        /// <summary>
        /// Find concrete data in all types by custom predicates.
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderby"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="recordCount"></param>
        /// <returns></returns>
        public IEnumerable<ConcreteDataObject> FindConcreteData(LinqPredicate predicate, string orderby, int pageIndex, int pageSize, out int recordCount)
        {
            try
            {
                using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                {
                    var q = from c in ctx.ConcreteDatas
                            where c.ApplicationId == authenticationContext.ApplicationId
                            select c;

                    if (predicate != null && !string.IsNullOrEmpty(predicate.Expression))
                        q = q.Where(predicate.Expression, predicate.Parameters);

                    if (!string.IsNullOrEmpty(orderby))
                        q = q.OrderBy(orderby);

                    recordCount = q.Count();

                    List<ConcreteDataObject> concreteDataObjects = new List<ConcreteDataObject>();
                    List<ConcreteData> concreteDataEntities = q.Skip(pageIndex * pageSize).Take(pageSize).ToList();
                    foreach (ConcreteData entity in concreteDataEntities)
                    {
                        ConcreteDataObject concreteDataObject = new ConcreteDataObject
                        {
                            ConcreteDataId = entity.ConcreteDataId,
                            Type = entity.Type,
                            CreatedBy = entity.CreatedBy,
                            CreatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(entity.CreatedDate),
                            DeleteStatus = entity.DeleteStatus,
                            Description = entity.Description,
                            ExtensionDataTypeId = entity.ExtensionDataTypeId,
                            LastUpdatedBy = entity.LastUpdatedBy,
                            LastUpdatedDate = LocalizationUtility.ConvertUtcTimeToClientTime(entity.LastUpdatedDate),
                            Name = entity.Name,
                            Value = entity.Value
                        };

                        concreteDataObject.ParseExtensionPropertiesFrom(entity);
                        concreteDataObjects.Add(concreteDataObject);
                    }

                    return concreteDataObjects;
                }
            }
            catch (Exception exp)
            {
                Logger.Instance(this).Error(exp);
                throw;
            }
        }