예제 #1
0
        // Enter a new shard - i.e. an empty database - to the shard map, allocate a first tenant to it 
        // and kick off EF intialization of the database to deploy schema
        // public void RegisterNewShard(string server, string database, string user, string pwd, string appname, int key)
        public void RegisterNewShard(string server, string database, string connstr, int key)
        {
            Shard shard;
            ShardLocation shardLocation = new ShardLocation(server, database);

            if (!this.ShardMap.TryGetShard(shardLocation, out shard))
            {
                shard = this.ShardMap.CreateShard(shardLocation);
            }

            SqlConnectionStringBuilder connStrBldr = new SqlConnectionStringBuilder(connstr);
            connStrBldr.DataSource = server;
            connStrBldr.InitialCatalog = database;

            // Go into a DbContext to trigger migrations and schema deployment for the new shard.
            // This requires an un-opened connection.
            using (var db = new ElasticScaleContext<int>(connStrBldr.ConnectionString))
            {
                // Run a query to engage EF migrations
                (from b in db.Blogs
                 select b).Count();
            }

            // 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 (!this.ShardMap.TryGetMappingForKey(key, out mapping))
            {
                this.ShardMap.CreatePointMapping(key, shard);
            }
        }
예제 #2
0
        protected override void Seed(ElasticScaleContext <int> context)
        {
            // This method will be called after migrating to the latest version.

            // You can use the DbSet<T>.AddOrUpdate() helper extension method
            // to avoid creating duplicate seed data. E.g.
            //
            // context.People.AddOrUpdate(
            //   p => p.FullName,
            //   new Person { FullName = "Andrew Peters" },
            //   new Person { FullName = "Brice Lambson" },
            //   new Person { FullName = "Rowan Miller" }
            // );
        }
예제 #3
0
        public static void Main()
        {
            SqlConnectionStringBuilder connStrBldr = new SqlConnectionStringBuilder
            {
                UserID = s_userName,
                Password = s_password,
                ApplicationName = s_applicationName
            };

            // Bootstrap the shard map manager, register shards, and store mappings of tenants to shards
            // Note that you can keep working with existing shard maps. There is no need to 
            // re-create and populate the shard map from scratch every time.
            Console.WriteLine("Checking for existing shard map and creating new shard map if necessary.");

            Sharding sharding = new Sharding(s_server, s_shardmapmgrdb, connStrBldr.ConnectionString);
            sharding.RegisterNewShard(s_server, s_shard1, connStrBldr.ConnectionString, s_tenantId1);
            sharding.RegisterNewShard(s_server, s_shard2, connStrBldr.ConnectionString, s_tenantId2);

            // Do work for tenant 1 :-)

            // Create and save a new Blog 
            Console.Write("Enter a name for a new Blog: ");
            var name = Console.ReadLine();

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, s_tenantId1, connStrBldr.ConnectionString))
                {
                    var blog = new Blog { Name = name };
                    db.Blogs.Add(blog);
                    db.SaveChanges();
                }
            });

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, s_tenantId1, connStrBldr.ConnectionString))
                {
                    // Display all Blogs for tenant 1
                    var query = from b in db.Blogs
                                orderby b.Name
                                select b;

                    Console.WriteLine("All blogs for tenant id {0}:", s_tenantId1);
                    foreach (var item in query)
                    {
                        Console.WriteLine(item.Name);
                    }
                }
            });

            // Do work for tenant 2 :-)
            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, s_tenantId2, connStrBldr.ConnectionString))
                {
                    // Display all Blogs from the database 
                    var query = from b in db.Blogs
                                orderby b.Name
                                select b;

                    Console.WriteLine("All blogs for tenant id {0}:", s_tenantId2);
                    foreach (var item in query)
                    {
                        Console.WriteLine(item.Name);
                    }
                }
            });

            // Create and save a new Blog 
            Console.Write("Enter a name for a new Blog: ");
            var name2 = Console.ReadLine();

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, s_tenantId2, connStrBldr.ConnectionString))
                {
                    var blog = new Blog { Name = name2 };
                    db.Blogs.Add(blog);
                    db.SaveChanges();
                }
            });

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, s_tenantId2, connStrBldr.ConnectionString))
                {
                    // Display all Blogs from the database 
                    var query = from b in db.Blogs
                                orderby b.Name
                                select b;

                    Console.WriteLine("All blogs for tenant id {0}:", s_tenantId2);
                    foreach (var item in query)
                    {
                        Console.WriteLine(item.Name);
                    }
                }
            });

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
예제 #4
0
        public static void Main()
        {
            SqlConnectionStringBuilder connStrBldr = new SqlConnectionStringBuilder
            {
                UserID = userName,
                Password = password,
                ApplicationName = applicationName
            };

            #region Create Shards
            // Bootstrap the shard map manager, register shards, and store mappings of tenants to shards
            // Note that you can keep working with existing shard maps. There is no need to
            // re-create and populate the shard map from scratch every time.
            Console.WriteLine("Checking for existing shard map and creating new shard map if necessary.");

            Sharding sharding = new Sharding(server, shardmapmgrdb, connStrBldr.ConnectionString);
            sharding.RegisterNewShard(server, shard1, connStrBldr.ConnectionString, tenantId1);
            sharding.RegisterNewShard(server, shard2, connStrBldr.ConnectionString, tenantId2);

            #endregion

            #region Insert Items
            // Do work for tenant 1 :-)

            // Create and save a new Blog
            Console.Write("Enter a name for a new Blog: ");
            var name = Console.ReadLine();

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId1, connStrBldr.ConnectionString))
                {
                    var blog = new Blog { Name = name };
                    db.Blogs.Add(blog);
                    db.SaveChanges();
                }
            });

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId1, connStrBldr.ConnectionString))
                {
                    // Display all Blogs for tenant 1
                    var query = from b in db.Blogs
                                orderby b.Name
                                select b;

                    Console.WriteLine("All blogs for tenant id {0}:", tenantId1);
                    foreach (var item in query)
                    {
                        Console.WriteLine(item.Name);
                    }
                }
            });

            // Do work for tenant 2 :-)
            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId2, connStrBldr.ConnectionString))
                {
                    // Display all Blogs from the database
                    var query = from b in db.Blogs
                                orderby b.Name
                                select b;

                    Console.WriteLine("All blogs for tenant id {0}:", tenantId2);
                    foreach (var item in query)
                    {
                        Console.WriteLine(item.Name);
                    }
                }
            });

            // Create and save a new Blog
            Console.Write("Enter a name for a new Blog: ");
            var name2 = Console.ReadLine();

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId2, connStrBldr.ConnectionString))
                {
                    var blog = new Blog { Name = name2 };
                    db.Blogs.Add(blog);
                    db.SaveChanges();
                }
            });

            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId2, connStrBldr.ConnectionString))
                {
                    // Display all Blogs from the database
                    var query = from b in db.Blogs
                            orderby b.Name
                            select b;

                    Console.WriteLine("All blogs for tenant id {0}:", tenantId2);
                    foreach (var item in query)
                    {
                        Console.WriteLine(item.Name);
                    }
                }
            });

            #endregion

            #region Query

            Console.WriteLine("Staring Multi Shard Read via MultiShardCommand");

            /// Multi Shard querying
            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (MultiShardConnection conn = new MultiShardConnection(
                                    sharding.ShardMap.GetShards(),
                                    connStrBldr.ConnectionString))
                {

                    using (MultiShardCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "SELECT BlogId, Name FROM Blogs";
                        cmd.CommandType = CommandType.Text;
                        cmd.ExecutionOptions = MultiShardExecutionOptions.IncludeShardNameColumn;
                        cmd.ExecutionPolicy = MultiShardExecutionPolicy.PartialResults;

                        using (MultiShardDataReader sdr = cmd.ExecuteReader())
                        {
                            while (sdr.Read())
                            {
                                var c2Field = sdr.GetFieldValue<int>(0);
                                var c1Field = sdr.GetFieldValue<string>(1);

                                Blog blog = new Blog(c2Field, c1Field, null);

                                Console.WriteLine("Blog Entry: " + blog.Name);
                            }
                        }
                    }
                }
            });

            Console.WriteLine("Staring Multi Shard Read via Elastic Scale");

            //Elastic Query
            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (SqlConnection conn = new SqlConnection(elasticqueryString))
                {
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "SELECT BlogId, Name FROM Blogs";
                        cmd.CommandType = CommandType.Text;

                        conn.Open();

                        using (SqlDataReader sdr = cmd.ExecuteReader())
                        {
                            while (sdr.Read())
                            {
                                var c2Field = sdr.GetFieldValue<int>(0);
                                var c1Field = sdr.GetFieldValue<string>(1);

                                Blog blog = new Blog(c2Field, c1Field, null);

                                Console.WriteLine("Blog Entry: " + blog.Name);
                            }
                        }
                    }
                }
            });

            #endregion

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
예제 #5
0
        public static void Main()
        {
            SqlConnectionStringBuilder connStrBldr = new SqlConnectionStringBuilder
            {
                UserID = s_userName,
                Password = s_password,
                ApplicationName = s_applicationName
            };

            // Bootstrap the shard map manager, register shards, and store mappings of tenants to shards.
            // Note that you can keep working with existing shard maps. There is no need to 
            // re-create and populate the shard map from scratch every time.
            Console.WriteLine("Checking for existing shard map and creating new shard map if necessary.");

            Sharding sharding = new Sharding(s_server, s_shardmapmgrdb, connStrBldr.ConnectionString);
            sharding.RegisterNewShard(s_server, s_shard1, connStrBldr.ConnectionString, s_tenantId1);
            sharding.RegisterNewShard(s_server, s_shard2, connStrBldr.ConnectionString, s_tenantId2);
            sharding.RegisterNewShard(s_server, s_shard1, connStrBldr.ConnectionString, s_tenantId3);
            sharding.RegisterNewShard(s_server, s_shard2, connStrBldr.ConnectionString, s_tenantId4);

            // Using Entity Framework and LINQ, create a new blog and then display all blogs for each tenant
            Console.WriteLine("\n--\n\nCreate a new blog for each tenant, then list the blogs belonging to that tenant.");
            Console.WriteLine("If row-level security has not been enabled, then the blogs for all tenants on the shard database will be listed.");

            int[] tenants = new int[] { s_tenantId1, s_tenantId2, s_tenantId3, s_tenantId4 };
            foreach (int tenantId in tenants)
            {
                Console.Write("\nEnter a name for a new Blog for TenantId {0}: ", tenantId);
                var name = Console.ReadLine();

                SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
                {
                    using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId, connStrBldr.ConnectionString))
                    {
                        var blog = new Blog { Name = name, TenantId = tenantId }; // must specify TenantId unless using default constraints to auto-populate
                        db.Blogs.Add(blog);
                        db.SaveChanges();

                        // If Row-Level Security is enabled, tenants will only display their own blogs
                        // Otherwise, tenants will see blogs for all tenants on the shard db
                        var query = from b in db.Blogs
                                    orderby b.Name
                                    select b;

                        Console.WriteLine("All blogs for TenantId {0}:", tenantId);
                        foreach (var item in query)
                        {
                            Console.WriteLine(item.Name);
                        }
                    }
                });
            }

            // Example query via ADO.NET SqlClient
            // If Row-Level Security is enabled, only Tenant 4's blogs will be listed
            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                // Note: We are using a wrapper function OpenDDRConnection that automatically set SESSION_CONTEXT with the specified TenantId. 
                // This is a best practice to ensure that SESSION_CONTEXT is always set before executing a query.
                using (SqlConnection conn = ElasticScaleContext<int>.OpenDDRConnection(sharding.ShardMap, s_tenantId4, connStrBldr.ConnectionString))
                {
                    SqlCommand cmd = conn.CreateCommand();
                    cmd.CommandText = @"SELECT * FROM Blogs";

                    Console.WriteLine("\n--\n\nAll blogs for TenantId {0} (using ADO.NET SqlClient):", s_tenantId4);
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine("{0}", reader["Name"]);
                    }
                }
            });

            // Because of the RLS block predicate, attempting to insert a row for the wrong tenant will throw an error.
            Console.WriteLine("\n--\n\nTrying to create a new Blog for TenantId {0} while connected as TenantId {1}: ", s_tenantId2, s_tenantId3);
            SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
            {
                using (var db = new ElasticScaleContext<int>(sharding.ShardMap, s_tenantId3, connStrBldr.ConnectionString))
                {
                    // Verify that block predicate prevents Tenant 3 from inserting rows for Tenant 2
                    try
                    {
                        var bad_blog = new Blog { Name = "BAD BLOG", TenantId = s_tenantId2 };
                        db.Blogs.Add(bad_blog);
                        db.SaveChanges();
                        Console.WriteLine("No error thrown - make sure your security policy has a block predicate on this table in each shard database.");
                    }
                    catch (DbUpdateException)
                    {
                        Console.WriteLine("Can't insert blog for incorrect tenant.");
                    }
                }
            });

            Console.WriteLine("\n--\n\nPress any key to exit...");
            Console.ReadKey();
        }