/// <summary>
        ///Bind the files with id of the external object.
        /// </summary>
        /// <param name="relationshipType"></param>
        /// <param name="externalObjectId"></param>
        /// <param name="fileIds"></param>
        public void Bind(string relationshipType, Guid externalObjectId, IEnumerable<Guid> fileIds)
        {
            try
            {
                using (TransactionScope ts = new TransactionScope())
                using (FileManagementDataContext ctx = DataContextFactory.Create<FileManagementDataContext>())
                {
                    List<Guid> associatedFileIds = (from f in ctx.FileBindings
                                                   where f.ApplicationId == applicationContext.ApplicationId
                                                        && f.RelationshipType == relationshipType
                                                        && f.ExtenalObjectId == externalObjectId
                                                   select f.FileId).Distinct().ToList();

                    foreach (Guid fileId in fileIds)
                    {
                        if (associatedFileIds.Contains(fileId)) continue;
                        ctx.FileBindings.InsertOnSubmit(new FileBinding
                              {
                                  ApplicationId = this.applicationContext.ApplicationId,
                                  RelationshipType = relationshipType,
                                  ExtenalObjectId = externalObjectId,
                                  FileId = fileId
                              });
                    }

                    ctx.SubmitChanges();
                    ts.Complete();
                }
            }
            catch (Exception exp)
            {
                Logger.Instance(this).Error(exp);
                throw;
            }
        }
        public void CacheCommittedWithTransactionTest()
        {
            string applicationName = "CacheWithinTransactionScopeTest";
            string cacheKey = "CacheWithinTransactionScopeTest.CacheKey";
            ICache cache = SpringContext.Current.GetObject<ICache>();

            using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
            using (TransactionScope transactionScope = new TransactionScope())
            {
                // create a new application to database
                Application application = new Application
                {
                    ApplicationName = applicationName,
                    LoweredApplicationName = applicationName.ToLowerInvariant(),
                    Description = ""
                };

                ctx.Applications.InsertOnSubmit(application);
                ctx.SubmitChanges();

                // save it into cache for 1 hour
                cache.Add(cacheKey, application, new TimeSpan(1, 0, 0), CachePriorityTypes.High);

                // the application should exist in both database and cache in the transaction
                Assert.AreEqual(1, ctx.Applications.Count(app => app.ApplicationName == applicationName), "The application should exist in database.");
                Assert.IsNotNull(cache.Get(cacheKey), "The application should exist in cache.");

                // complete the transaction
                transactionScope.Complete();
            }

            using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
            {
                // the application should exist in both database and cache in the transaction
                Assert.AreEqual(1, ctx.Applications.Count(app => app.ApplicationName == applicationName), "The application should exist in database.");
                Assert.IsNotNull(cache.Get(cacheKey), "The application should exist in cache.");

                // clear testing data.
                ctx.Applications.Delete(app => app.ApplicationName == applicationName);
                cache.Remove(cacheKey);
            }
        }
        /// <summary>
        /// Create sequence number on specified type for special object id.
        /// The method generates the sequence number suppressing transaction scope which means the generated sequence number cannot be rollback.
        /// </summary>
        /// <param name="objectId">E.g. we want each company in the system owns standalone sequence number generation. That means company A can have a sequence number 999 as company B has it meanwhile.</param>
        /// <param name="sequenceNoType">Sequence number type that means a company for above example can has multiple sequence number generation path. E.g. company A has a Order sequence number 999 as it has a Product sequence number 999 meanwhile.</param>
        /// <returns></returns>
        public long Create(Guid objectId, string sequenceNoType)
        {
            lock (syncObj)
            {
                try
                {
                    using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Suppress))
                    using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                    {
                        SequenceNo sequenceNo = ctx.SequenceNos.Where(s => s.ObjectId.Equals(objectId)
                            && s.Type.Equals(sequenceNoType)
                            && s.ApplicationId == this.authenticationContext.ApplicationId).FirstOrDefault();

                        if (sequenceNo == null)
                        {
                            sequenceNo = new SequenceNo()
                            {
                                ApplicationId = this.authenticationContext.ApplicationId,
                                ObjectId = objectId,
                                Type = sequenceNoType,
                                Number = 1
                            };

                            ctx.SequenceNos.InsertOnSubmit(sequenceNo);
                        }
                        else
                        {
                            sequenceNo.Number++;
                        }

                        ctx.SubmitChanges();
                        ts.Complete();
                        return sequenceNo.Number;
                    }
                }
                catch (Exception exp)
                {
                    Logger.Instance(this).Error(exp);
                    throw;
                }
            }
        }
        /// <summary>
        /// Save organization business object. 
        /// If organizationObject.Id equals Guid.Empty, it means to save a new organization. 
        /// Otherwise it's updating an existed organization.
        /// </summary>
        /// <param name="organizationObject"></param>
        private void SaveOrganization(OrganizationObject organizationObject)
        {
            try
            {
                Organization organization = null;

                using (TransactionScope transactionScope = new TransactionScope())
                using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                {
                    using (ValidationScope validationScope = new ValidationScope(true))
                    {
                        // check duplicate organization name
                        int existedOrganizationCount = (from org in ctx.Organizations
                                                        where org.OrganizationName == organizationObject.OrganizationName
                                                             && org.ApplicationId == this.authenticationContext.ApplicationId
                                                             && org.OrganizationId != organizationObject.OrganizationId
                                                        select org).Count();
                        if (existedOrganizationCount > 0)
                            validationScope.Error(Resources.ExistedOrganizationName, organizationObject.OrganizationName);

                        // check duplicate organization code
                        if (!string.IsNullOrEmpty(organizationObject.OrganizationCode))
                        {
                            existedOrganizationCount = (from org in ctx.Organizations
                                                        where org.OrganizationCode == organizationObject.OrganizationCode
                                                             && org.ApplicationId == this.authenticationContext.ApplicationId
                                                             && org.OrganizationId != organizationObject.OrganizationId
                                                        select org).Count();
                            if (existedOrganizationCount > 0)
                                validationScope.Error(Resources.ExistedOrganizationCode, organizationObject.OrganizationCode);
                        }

                        // validate organization type
                        OrganizationTypeObject organizationTypeObject = this.GetOrganizationType(organizationObject.OrganizationTypeId);
                        if (organizationTypeObject == null)
                            validationScope.Error(Resources.InvalidOrganizationTypeID);

                        // validate organization located area
                        if (organizationObject.Hierarchies != null && organizationObject.Hierarchies.Count > 0)
                        {
                            foreach (string hierarchyType in organizationObject.Hierarchies.Keys)
                            {
                                HierarchyDataObject hierarchyDataObject = hierarchyApi.GetHierarchyData(organizationObject.Hierarchies[hierarchyType]);
                                if (hierarchyDataObject == null || !string.Equals(hierarchyDataObject.HierarchyType, hierarchyType, StringComparison.OrdinalIgnoreCase))
                                    validationScope.Error(Resources.InvalidHierarchyAssociatedWithOrganization, hierarchyType, hierarchyDataObject.HierarchyDataId);
                            }
                        }

                        // check circular reference of parent
                        if (organizationObject.ParentOrganizationId.HasValue)
                        {
                            if (organizationObject.OrganizationId == organizationObject.ParentOrganizationId.Value)
                                validationScope.Error(Resources.InvalidParentOrganizationID);

                            if (organizationObject.OrganizationId != organizationObject.ParentOrganizationId.Value)
                            {
                                List<string> existedOrganizationNames = new List<string>();
                                HashSet<Guid> existedOrganizationIds = new HashSet<Guid> { organizationObject.OrganizationId };
                                OrganizationObject parentOrganizationObject = this.GetOrganization(organizationObject.ParentOrganizationId.Value);

                                if (parentOrganizationObject == null)
                                    validationScope.Error(Resources.InvalidParentOrganizationID);
                                else
                                {
                                    this.VerifyStatusAgainstParentOrganization(parentOrganizationObject, organizationObject.Status, organizationObject.OrganizationName, validationScope);

                                    while (parentOrganizationObject != null)
                                    {
                                        existedOrganizationNames.Add(parentOrganizationObject.OrganizationName);
                                        if (existedOrganizationIds.Contains(parentOrganizationObject.OrganizationId))
                                        {
                                            validationScope.Error(Resources.ParentOrganizationCircularReference, FormatCircularOrganizationNames(existedOrganizationNames));
                                            break;
                                        }

                                        existedOrganizationIds.Add(parentOrganizationObject.OrganizationId);
                                        if (!parentOrganizationObject.ParentOrganizationId.HasValue) break;

                                        parentOrganizationObject = this.GetOrganization(parentOrganizationObject.ParentOrganizationId.Value);
                                    }
                                }
                            }
                        }

                        if (organizationObject.OrganizationId == Guid.Empty)
                        {
                            organization = ExtensionObjectFactory.Create<Organization>(organizationObject);
                            organization.OrganizationCode = organizationObject.OrganizationCode;
                            organization.CreatedDate = DateTime.UtcNow;
                            organization.CreatedBy = this.authenticationContext.User.UserId;

                            ctx.Organizations.InsertOnSubmit(organization);
                        }
                        else
                        {
                            organization = ctx.Organizations.FirstOrDefault(org => org.OrganizationId == organizationObject.OrganizationId);
                            if (organization == null)
                                validationScope.Error(Resources.InvalidOrganizationID);

                            organization.ExtensionDataTypeId = organizationObject.ExtensionDataTypeId;

                            if (organization.OrganizationCode != organizationObject.OrganizationCode)
                                validationScope.Error(Resources.CodeCannotUpdate);

                            // update status of all children only when updates status from Enabled to Disabled.
                            if (organizationObject.Status == OrganizationStatus.Disabled && organization.Status == OrganizationStatus.Enabled)
                                UpdateSubOrganizationsStatus(ctx, new[] { organization.OrganizationId }, organizationObject.Status);
                        }
                    }

                    organization.ApplicationId = this.authenticationContext.ApplicationId;
                    organization.OrganizationName = organizationObject.OrganizationName;
                    organization.OrganizationTypeId = organizationObject.OrganizationTypeId;
                    organization.ParentOrganizationId = organizationObject.ParentOrganizationId;
                    organization.Status = organizationObject.Status;
                    organization.Description = organizationObject.Description;
                    organization.LastUpdatedDate = DateTime.UtcNow;
                    organization.LastUpdatedBy = this.authenticationContext.User.UserId;

                    // remove original hierarchies and added new ones
                    if (organizationObject.OrganizationId != Guid.Empty && organization.Hierarchies.Count > 0)
                        ctx.OrganizationsInHierarchies.DeleteAllOnSubmit(organization.Hierarchies);

                    if (organizationObject.Hierarchies != null && organizationObject.Hierarchies.Count > 0)
                    {
                        foreach (string hierarchyType in organizationObject.Hierarchies.Keys)
                        {
                            HierarchyDataObject hierarchyDataObject = hierarchyApi.GetHierarchyData(organizationObject.Hierarchies[hierarchyType]);
                            if (hierarchyDataObject != null)
                            {
                                ctx.OrganizationsInHierarchies.InsertOnSubmit(new OrganizationsInHierarchy
                                {
                                    ApplicationId = authenticationContext.ApplicationId,
                                    HierarchyType = hierarchyType,
                                    HierarchyDataId = organizationObject.Hierarchies[hierarchyType],
                                    Organization = organization,
                                });
                            }
                        }
                    }

                    organization.ParseExtensionPropertiesFrom(organizationObject);

                    ctx.SubmitChanges();
                    transactionScope.Complete();

                    organizationObject.OrganizationId = organization.OrganizationId;
                    organizationObject.CreatedBy = organization.CreatedBy;
                    organizationObject.CreatedDate = organization.CreatedDate;
                    organizationObject.LastUpdatedBy = organization.LastUpdatedBy;
                    organizationObject.LastUpdatedDate = organization.LastUpdatedDate;
                }
            }
            catch (ValidationException)
            {
                throw;
            }
            catch (Exception exp)
            {
                Logger.Instance(this).Error(exp);
                throw;
            }
        }
        /// <summary>
        /// Save organization business object. 
        /// If organizationObject.Id equals Guid.Empty, it means to save a new organization. 
        /// Otherwise it's updating an existed organization.
        /// </summary>
        /// <param name="organizationObject"></param>
        public void Save(OrganizationObject organizationObject)
        {
            Kit.NotNull(organizationObject, "organizationObject");
            Kit.NotNull(organizationObject.OrganizationCode, "organizationObject.OrganizationCode");
            Kit.NotNull(organizationObject.OrganizationName, "organizationObject.OrganizationName");

            if (organizationObject.OrganizationTypeId == Guid.Empty)
                throw new ArgumentException(Resources.InvalidOrganizationTypeID);

            if (organizationObject.Status == OrganizationStatus.None)
                throw new ArgumentException(Resources.OrganizationStatusNotSpecified, "organizationObject.Status");

            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    bool isUpdate = organizationObject.OrganizationId != Guid.Empty;
                    this.SaveOrganization(organizationObject);

                    // remove the cache for update
                    if (isUpdate)
                        base.RemoveCache(organizationObject.OrganizationId);

                    transactionScope.Complete();
                    UpdateTimeZone(organizationObject);
                }
            }
            catch (ValidationException)
            {
                throw;
            }
            catch (Exception exp)
            {
                Logger.Instance(this).Error(exp);
                throw;
            }
        }
        /// <summary>
        /// Set permissions on specified user.
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="permissions"></param>
        public void SetUserPermissions(Guid userId, IEnumerable<string> permissions)
        {
            Kit.NotNull(permissions, "permissions");

            try
            {
                using (TransactionScope ts = new TransactionScope())
                using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                {
                    ctx.Permissions.Delete(p => p.UserId == userId);
                    foreach (string permission in permissions.Distinct())
                    {
                        ctx.Permissions.InsertOnSubmit(new Permission() { UserId = userId, PermissionKey = permission });
                    }

                    ctx.SubmitChanges();
                    base.RemoveCache(userId);
                    ts.Complete();
                }
            }
            catch (Exception exp)
            {
                Logger.Instance(this).Error(exp);
                throw;
            }
        }
        public void RegisterCallbackToTransactionStatusChangedTest()
        {
            object locker = new object();
            List<int> newTransactionThreadIds = new List<int>();
            List<int> completedTransactionThreadIds = new List<int>();
            List<int> rollbackTransactionThreadIds = new List<int>();

            TransactionScopeContext.AfterNewTransactionStarted += threadId =>
                {
                    newTransactionThreadIds.Remove(threadId);
                };

            TransactionScopeContext.AfterTransactionCommitted += threadId =>
                {
                    completedTransactionThreadIds.Remove(threadId);
                };

            TransactionScopeContext.AfterTransactionRollback += threadId =>
                {
                    rollbackTransactionThreadIds.Remove(threadId);
                };

            WaitCallback waitTransactionCompleteCallback = state =>
                {
                    Monitor.Enter(locker);
                    try
                    {
                        newTransactionThreadIds.Add(Thread.CurrentThread.ManagedThreadId);
                        using (TransactionScope transactionScope = new TransactionScope())
                        {
                            completedTransactionThreadIds.Add(Thread.CurrentThread.ManagedThreadId);
                            transactionScope.Complete();
                        }
                    }
                    finally
                    {
                        Monitor.Exit(locker);
                    }
                };

            WaitCallback waitTransactionRollbackCallback = state =>
            {
                Monitor.Enter(locker);
                try
                {
                    newTransactionThreadIds.Add(Thread.CurrentThread.ManagedThreadId);
                    using (TransactionScope transactionScope = new TransactionScope())
                    {
                        rollbackTransactionThreadIds.Add(Thread.CurrentThread.ManagedThreadId);

                        // don't commit the transaction
                    }
                }
                finally
                {
                    Monitor.Exit(locker);
                }
            };

            ThreadPool.QueueUserWorkItem(waitTransactionCompleteCallback);
            ThreadPool.QueueUserWorkItem(waitTransactionRollbackCallback);

            Thread.Sleep(500);
            Monitor.Enter(locker);
            try
            {
                Assert.AreEqual(0, newTransactionThreadIds.Count, "The thread Ids should be removed in the registered callback.");
                Assert.AreEqual(0, completedTransactionThreadIds.Count, "The thread Ids should be removed in the registered callback.");
                Assert.AreEqual(0, rollbackTransactionThreadIds.Count, "The thread Ids should be removed in the registered callback.");
            }
            finally
            {
                Monitor.Exit(locker);
            }
        }
        /// <summary>
        /// Update an existed organization type from detail panel.
        /// The method needs to load an existed entity by specified id and set control values to overwrite its original properties then persist it.
        /// </summary>
        /// <param name="entityId"></param>
        public override void Update(string entityId)
        {
            this.ValidateDataInputForm(new Guid(entityId));

            using (TransactionScope ts = new TransactionScope())
            {
                UserObject userObject = membershipApi.Get(new Guid(entityId));
                userObject.ExtensionDataTypeId = this.ResolveUserExtensionDataTypeId();
                if (this.UserExtensionDataForm != null)
                    this.UserExtensionDataForm.SetObjectPropertiesFromControlValues(userObject);

                this.SetUserPropertiesFromControls(userObject);

                string password = null;
                if (this.TextBoxPassword != null)
                    password = this.TextBoxPassword.Text;

                membershipApi.Save(userObject, password, null);

                if (this.OrganizationSelector != null)
                {
                    OrganizationObject organizationObject = organizationApi.GetOrganization(this.OrganizationSelector.SelectedOrganization.OrganizationId);
                    IEnumerable<Guid> roleIds = this.ResolveSelectedRoleCheckBox(organizationObject);
                    roleApi.SetUserToRoles(userObject.UserId, roleIds);
                }

                if (this.PermissionTreeView != null)
                    permissionApi.SetUserPermissions(userObject.UserId, @PermissionTreeView.CheckedValues);

                ts.Complete();
            }
        }
        /// <summary>
        /// Set the user into the roles.
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="roleIds"></param>
        protected static void SetUserToRoles(Guid userId, IEnumerable<Guid> roleIds)
        {
            using (TransactionScope ts = new TransactionScope())
            using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
            {
                ctx.UsersInRoles.Delete(uir => uir.UserId == userId);
                foreach (Guid roleId in roleIds)
                    ctx.UsersInRoles.InsertOnSubmit(new UsersInRole { UserId = userId, RoleId = roleId });

                ctx.SubmitChanges();
                ts.Complete();
            }
        }
        /// <summary>
        /// Create a new role from detail panel and return the id.
        /// The method needs to create a new entity and set control values to its properties then persist it.
        /// </summary>
        /// <returns>returns the id of new created role.</returns>
        public override string Create()
        {
            this.ValidateInput(Guid.Empty);

            RoleObject roleObject = new RoleObject
            {
                RoleName = this.TextBoxName.Text,
                Description = this.TextBoxDescription.Text,
                Domain = authenticationContext.TempVariables["Domain.Value"] as string,
                Predefined = false
            };

            using (TransactionScope ts = new TransactionScope())
            {
                roleApi.Save(roleObject);
                permissionApi.SetRolePermissions(roleObject.RoleId, this.PermissionTreeView.CheckedValues);
                ts.Complete();
            }

            return roleObject.RoleId.ToString();
        }
        /// <summary>
        /// Update an existed organization type from detail panel.
        /// The method needs to load an existed entity by specified id and set control values to overwrite its original properties then persist it.
        /// </summary>
        /// <param name="entityId"></param>
        public override void Update(string entityId)
        {
            Guid roleId = new Guid(entityId);
            this.ValidateInput(roleId);

            RoleObject roleObject = new RoleObject { RoleId = roleId };
            roleObject.RoleName = this.TextBoxName.Text;
            roleObject.Description = this.TextBoxDescription.Text;
            roleObject.Domain = authenticationContext.TempVariables["Domain.Value"] as string;

            using (TransactionScope ts = new TransactionScope())
            {
                roleApi.Save(roleObject);
                permissionApi.SetRolePermissions(roleObject.RoleId, this.PermissionTreeView.CheckedValues);
                ts.Complete();
            }
        }
        /// <summary>
        /// Save organization type object.
        /// </summary>
        /// <param name="organizationTypeObject"></param>
        /// <exception cref="ValidationException">etc organization type name does exist.</exception>
        public void Save(OrganizationTypeObject organizationTypeObject)
        {
            Kit.NotNull(organizationTypeObject, "organizationTypeObject");
            Kit.NotNull(organizationTypeObject.Name, "organizationTypeObject.Name");
            if (!this.platformConfiguration.Domains.Select(d => d.Value).Contains(organizationTypeObject.Domain))
                throw new ArgumentException(string.Format(Resources.InvalidOrganizationTypeDomain, organizationTypeObject.Domain), "organizationTypeObject.Domain");

            Kit.NotNull(organizationTypeObject, "organizationTypeObject");
            Kit.NotNull(organizationTypeObject.Name, "organizationTypeObject.Name");
            if (!this.platformConfiguration.Domains.Select(d => d.Value).Contains(organizationTypeObject.Domain))
                throw new ArgumentException(string.Format(Resources.InvalidOrganizationTypeDomain, organizationTypeObject.Domain), "organizationTypeObject.Domain");

            try
            {
                using (TransactionScope ts = new TransactionScope())
                using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                {
                    OrganizationType organizationType = null;

                    DeleteStatus originalDeleteStatus = DeleteStatus.Deleted;
                    using (ValidationScope validationScope = new ValidationScope(true))
                    {
                        if (ctx.OrganizationTypes.Where(x => x.Name == organizationTypeObject.Name
                            && x.ApplicationId == this.authenticationContext.ApplicationId
                            && x.OrganizationTypeId != organizationTypeObject.OrganizationTypeId).Count() > 0)
                        {
                            validationScope.Error(Resources.ExistedOrganizationTypeName, organizationTypeObject.Name);
                        }

                        if (organizationTypeObject.OrganizationTypeId == Guid.Empty)
                        {
                            organizationType = new OrganizationType { ApplicationId = this.authenticationContext.ApplicationId };
                            ctx.OrganizationTypes.InsertOnSubmit(organizationType);
                        }
                        else
                        {
                            organizationType = ctx.OrganizationTypes.FirstOrDefault(orgType => orgType.OrganizationTypeId == organizationTypeObject.OrganizationTypeId);
                            if (organizationType == null)
                                validationScope.Error(Resources.InvalidOrganizationTypeID);

                            originalDeleteStatus = organizationType.DeleteStatus;
                        }
                    }

                    // set organization type properties.
                    organizationType.Domain = organizationTypeObject.Domain;
                    organizationType.Name = organizationTypeObject.Name;
                    organizationType.Description = organizationTypeObject.Description;
                    organizationType.LastUpdatedDate = DateTime.UtcNow;
                    organizationType.Predefined = organizationTypeObject.Predefined;
                    organizationType.DeleteStatus = organizationTypeObject.DeleteStatus;

                    // if disable an existed organization type
                    if (organizationTypeObject.OrganizationTypeId != Guid.Empty
                        && organizationTypeObject.DeleteStatus == DeleteStatus.Deleted
                        && organizationTypeObject.DeleteStatus != originalDeleteStatus)
                    {
                        // remove the cache copy for disabled organizations.
                        IEnumerable<Guid> disabledOrganizationIds = (from org in ctx.Organizations
                                                                     where org.ApplicationId == this.authenticationContext.ApplicationId
                                                                         && org.OrganizationTypeId == organizationTypeObject.OrganizationTypeId
                                                                         && org.Status != OrganizationStatus.Disabled
                                                                     select org.OrganizationId).ToList();

                        foreach (Guid disabledOrganizationId in disabledOrganizationIds)
                            base.RemoveCache(disabledOrganizationId);

                        // batch disable the organizations by sql command
                        string command = string.Format(CultureInfo.InvariantCulture, "UPDATE {0} SET Status={1} WHERE ApplicationId='{2}' AND OrganizationTypeId='{3}' AND Status<>{1}",
                            ctx.Mapping.GetTable(typeof(Organization)).TableName,
                            (int)OrganizationStatus.Disabled,
                            this.authenticationContext.ApplicationId,
                            organizationTypeObject.OrganizationTypeId);

                        ctx.ExecuteCommand(command);
                    }

                    ctx.SubmitChanges();
                    ts.Complete();

                    organizationTypeObject.OrganizationTypeId = organizationType.OrganizationTypeId;
                    organizationTypeObject.LastUpdatedDate = organizationType.LastUpdatedDate;

                    // remove cache.
                    base.RemoveCache(CacheKey4AllOrganizationTypes);
                }
            }
            catch (ValidationException)
            {
                throw;
            }
            catch (Exception exp)
            {
                Logger.Instance(this).Error(exp);
                throw;
            }
        }
        /// <summary>
        /// Create sequence numbers on specified type for special object id.
        ///  The method generates the sequence number suppressing transaction scope which means the generated sequence number cannot be rollback.
        /// </summary>
        /// <param name="objectId">E.g. we want each company in the system owns standalone sequence number generation. That means company A can have a sequence number 999 as company B has it meanwhile.</param>
        /// <param name="sequenceNoType">Sequence number type that means a company for above example can has multiple sequence number generation path. E.g. company A has a Order sequence number 999 as it has a Product sequence number 999 meanwhile.</param>
        /// <param name="sequenceNoCount">Indicates how many sequence number is required.</param>
        /// <returns></returns>
        public IEnumerable<long> Create(Guid objectId, string sequenceNoType, ushort sequenceNoCount)
        {
            if (sequenceNoCount <= 0)
                throw new ArgumentException("The argument \"sequenceNoCount\" should be more than zero.", "sequenceNoCount");

            lock (syncObj)
            {
                try
                {
                    using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Suppress))
                    using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
                    {
                        SequenceNo sequenceNo = ctx.SequenceNos.Where(s => s.ObjectId.Equals(objectId)
                            && s.Type.Equals(sequenceNoType)
                            && s.ApplicationId == this.authenticationContext.ApplicationId).FirstOrDefault();

                        long startSequenceNo;
                        if (sequenceNo == null)
                        {
                            sequenceNo = new SequenceNo()
                            {
                                ApplicationId = this.authenticationContext.ApplicationId,
                                ObjectId = objectId,
                                Type = sequenceNoType,
                                Number = sequenceNoCount
                            };

                            startSequenceNo = 1;
                            ctx.SequenceNos.InsertOnSubmit(sequenceNo);
                        }
                        else
                        {
                            startSequenceNo = sequenceNo.Number + 1;
                            sequenceNo.Number += sequenceNoCount;
                        }

                        ctx.SubmitChanges();
                        ts.Complete();

                        List<long> sequenceNumbers = new List<long>();
                        for (long i = startSequenceNo; i < startSequenceNo + sequenceNoCount; i++)
                            sequenceNumbers.Add(i);

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