Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Sharding" /> class.
        /// <para>Bootstrap Elastic Scale by creating a new shard map manager and a shard map on the shard map manager database if necessary.</para>
        /// </summary>
        /// <param name="catalogConfig">The catalog configuration.</param>
        /// <param name="databaseConfig">The database configuration.</param>
        /// <param name="tenantsRepository">The tenants repository.</param>
        /// <param name="helper">The helper.</param>
        public Sharding(CatalogConfig catalogConfig, DatabaseConfig databaseConfig, ITenantsRepository tenantsRepository, IHelper helper)
        {
            try
            {
                _tenantsRepository = tenantsRepository;
                _helper            = helper;

                var smmconnstr = _helper.GetSqlConnectionString(databaseConfig, catalogConfig);

                // Deploy shard map manager
                // if shard map manager exists, refresh content, else create it, then add content
                ShardMapManager smm;
                ShardMapManager =
                    !ShardMapManagerFactory.TryGetSqlShardMapManager(smmconnstr,
                                                                     ShardMapManagerLoadPolicy.Lazy, out smm)
                        ? ShardMapManagerFactory.CreateSqlShardMapManager(smmconnstr)
                        : smm;

                // check if shard map exists and if not, create it
                ListShardMap <int> sm;
                ShardMap = !ShardMapManager.TryGetListShardMap(catalogConfig.CatalogDatabase, out sm)
                    ? ShardMapManager.CreateListShardMap <int>(catalogConfig.CatalogDatabase)
                    : sm;
            }
            catch (Exception ex)
            {
                // _logger.LogError(0, ex, "Error in sharding initialisation.");
                throw new ApplicationException("Error in sharding initialisation.");
            }
        }
Example #2
0
        /// <summary>
        /// Register tenant shard
        /// </summary>
        /// <param name="tenantServerConfig">The tenant server configuration.</param>
        /// <param name="databaseConfig">The database configuration.</param>
        /// <param name="catalogConfig">The catalog configuration.</param>
        /// <param name="resetEventDate">If set to true, the events dates for all tenants will be reset </param>
        public async void RegisterTenantShard(TenantServerConfig tenantServerConfig, DatabaseConfig databaseConfig, CatalogConfig catalogConfig, bool resetEventDate)
        {
            //get all database in devtenantserver
            var tenants = GetAllTenantNames(tenantServerConfig, databaseConfig);

            var connectionString = new SqlConnectionStringBuilder
            {
                UserID          = databaseConfig.DatabaseUser,
                Password        = databaseConfig.DatabasePassword,
                ApplicationName = "EntityFramework",
                ConnectTimeout  = databaseConfig.ConnectionTimeOut
            };

            Shard shard = Sharding.CreateNewShard(tenantServerConfig.TenantDatabase, tenantServerConfig.TenantServer, databaseConfig.DatabaseServerPort, catalogConfig.ServicePlan);

            foreach (var tenant in tenants)
            {
                var tenantId = GetTenantKey(tenant);
                var result   = await Sharding.RegisterNewShard(tenantId, catalogConfig.ServicePlan, shard);

                if (result)
                {
                    // resets all tenants' event dates
                    if (resetEventDate)
                    {
                        #region EF6
                        //use EF6 since execution of Stored Procedure in EF Core for anonymous return type is not supported yet
                        using (var context = new TenantContext(Sharding.ShardMap, tenantId, connectionString.ConnectionString))
                        {
                            //context.Database.ExecuteSqlCommand("sp_ResetEventDates");
                        }
                        #endregion

                        #region EF core
                        //https://github.com/aspnet/EntityFramework/issues/7032
                        //using (var context = new TenantDbContext(Sharding.ShardMap, tenantId, connectionString))
                        //{
                        //    context.Database.ExecuteSqlCommand("sp_ResetEventDates");
                        //}
                        #endregion
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Registers the new shard.
        /// Verify if shard exists for the tenant. If not then create new shard and add tenant details to Tenants table in catalog
        /// </summary>
        /// <param name="tenantName">Name of the tenant.</param>
        /// <param name="tenantId">The tenant identifier.</param>
        /// <param name="tenantServerConfig">The tenant server configuration.</param>
        /// <param name="databaseConfig">The database configuration.</param>
        /// <param name="catalogConfig">The catalog configuration.</param>
        public static bool RegisterNewShard(string tenantName, int tenantId, TenantServerConfig tenantServerConfig, DatabaseConfig databaseConfig, CatalogConfig catalogConfig)
        {
            try
            {
                Shard         shard;
                ShardLocation shardLocation = new ShardLocation(tenantServerConfig.TenantServer, tenantName, databaseConfig.SqlProtocol, databaseConfig.DatabaseServerPort);

                if (!ShardMap.TryGetShard(shardLocation, out shard))
                {
                    //create shard if it does not exist
                    shard = ShardMap.CreateShard(shardLocation);
                }


                // Register the mapping of the tenant to the shard in the shard map.
                // After this step, DDR on the shard map can be used
                PointMapping <int> mapping;
                if (!ShardMap.TryGetMappingForKey(tenantId, out mapping))
                {
                    var pointMapping = ShardMap.CreatePointMapping(tenantId, shard);

                    //convert from int to byte[] as tenantId has been set as byte[] in Tenants entity
                    var key = _helper.ConvertIntKeyToBytesArray(pointMapping.Value);

                    //add tenant to Tenants table
                    var tenant = new Tenants
                    {
                        ServicePlan = catalogConfig.ServicePlan,
                        TenantId    = key,
                        TenantName  = tenantName
                    };

                    _tenantsRepository.Add(tenant);
                }
                return(true);
            }
            catch (Exception ex)
            {
                // _logger.LogError(0, ex, "Error in registering new shard.");
                //throw new ApplicationException("Error in registering new shard.");
                return(false);
            }
        }
Example #4
0
        /// <summary>
        /// Register tenant shard
        /// </summary>
        /// <param name="tenantServerConfig">The tenant server configuration.</param>
        /// <param name="databaseConfig">The database configuration.</param>
        /// <param name="catalogConfig">The catalog configuration.</param>
        /// <param name="resetEventDate">If set to true, the events dates for all tenants will be reset </param>
        public async void RegisterTenantShard(TenantServerConfig tenantServerConfig, DatabaseConfig databaseConfig, CatalogConfig catalogConfig, bool resetEventDate)
        {
            //get all database in devtenantserver
            var tenants = GetAllTenantNames(tenantServerConfig, databaseConfig);

            var connectionString = new SqlConnectionStringBuilder
            {
                UserID          = databaseConfig.DatabaseUser,
                Password        = databaseConfig.DatabasePassword,
                ApplicationName = "EntityFramework",
                ConnectTimeout  = databaseConfig.ConnectionTimeOut
            };

            foreach (var tenant in tenants)
            {
                var tenantId = GetTenantKey(tenant);
                var result   = await Sharding.RegisterNewShard(tenant, tenantId, tenantServerConfig.TenantServer, databaseConfig.DatabaseServerPort, catalogConfig.ServicePlan);

                if (result)
                {
                    // resets all tenants' event dates
                    if (resetEventDate)
                    {
                        #region EF6
                        try
                        {
                            //use EF6 since execution of Stored Procedure in EF Core for anonymous return type is not supported yet
                            using (var context = new TenantContext(Sharding.ShardMap, tenantId, connectionString.ConnectionString))
                            {
                                context.Database.ExecuteSqlCommand("sp_ResetEventDates");
                            }
                        }
                        catch (Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement.ShardManagementException ex)
                        {
                            string errorText;
                            if (ex.ErrorCode == Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement.ShardManagementErrorCode.MappingIsOffline)
                            {
                                errorText = "Tenant '" + tenant + "' is offline. Could not reset event dates:" + ex.ToString();
                            }
                            else
                            {
                                errorText = ex.ToString();
                            }
                            Console.WriteLine(errorText);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.ToString());
                        }
                        #endregion

                        #region EF core
                        //https://github.com/aspnet/EntityFramework/issues/7032
                        //using (var context = new TenantDbContext(Sharding.ShardMap, tenantId, connectionString))
                        //{
                        //     context.Database.ExecuteSqlCommand("sp_ResetEventDates");
                        //}
                        #endregion
                    }
                }
            }
        }