Azure Elastic Scale 分片密钥
Azure Elastic Scale Sharding Key
我正在将我的数据模型移动到 Azure Elastic Scale。
经过一些测试和一些体验后,我爱上了它,它很简单,而且采用这种方法,代码保持干净且易于维护。
我只有一个大问题,分片键在哪里定义?我找不到有关从 Visual Studio 下载的示例的信息,我可以确定这是一个直接的答案。
在 Microsoft 提供的示例中,默认分片键是 CustomerId,但我找不到对该键的引用。
会不会在配置文件的 ShardMapName 中?
提前致谢。
SQL 架构中的分片键与其用法(在代码中)之间没有明确的 link。
所以在入门示例中,客户和订单 table 都包含一个 CustomerId
列,当我们访问这些 tables 我们确保向 shardMap.OpenConnectionForKey
方法提供相同的 customerId
值,然后在以下查询中将其用于 customerId 列(在 SELECT 和 INSERT 语句中)。
// Looks up the key in the shard map and opens a connection to the shard
using (SqlConnection conn = shardMap.OpenConnectionForKey(customerId, credentialsConnectionString))
{
// Create a simple command that will insert or update the customer information
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"
IF EXISTS (SELECT 1 FROM Customers WHERE CustomerId = @customerId)
UPDATE Customers
SET Name = @name, RegionId = @regionId
WHERE CustomerId = @customerId
ELSE
INSERT INTO Customers (CustomerId, Name, RegionId)
VALUES (@customerId, @name, @regionId)";
cmd.Parameters.AddWithValue("@customerId", customerId);
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@regionId", regionId);
cmd.CommandTimeout = 60;
// Execute the command
cmd.ExecuteNonQuery();
}
换句话说,当您在 OpenConnectionForKey
调用中提供某个键值时,您有责任确保所有具有该连接的 SQL 查询都限于该键值,否则您最终可能会得到不正确的结果(例如,如果它是一个 SELECT 查询)或位于错误分片上的行(例如,如果它是一个 INSERT 查询)。
可以使用新的行级安全功能解决此安全问题。我们有一个名为 Entity Framework Multi-Tenant Shards that demonstrates how to combine Shard Maps with Row-Level Security. The relevant code is in ElasticScaleContext.cs:
的示例
SqlConnection conn = null;
try
{
// Ask shard map to broker a validated connection for the given key
conn = shardMap.OpenConnectionForKey(shardingKey, connectionStr, ConnectionOptions.Validate);
// Set CONTEXT_INFO to shardingKey to enable Row-Level Security filtering
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"SET CONTEXT_INFO @shardingKey";
cmd.Parameters.AddWithValue("@shardingKey", shardingKey);
cmd.ExecuteNonQuery();
return conn;
}
catch (Exception)
{
if (conn != null)
{
conn.Dispose();
}
throw;
}
谢谢你的好问题!
我正在将我的数据模型移动到 Azure Elastic Scale。
经过一些测试和一些体验后,我爱上了它,它很简单,而且采用这种方法,代码保持干净且易于维护。
我只有一个大问题,分片键在哪里定义?我找不到有关从 Visual Studio 下载的示例的信息,我可以确定这是一个直接的答案。
在 Microsoft 提供的示例中,默认分片键是 CustomerId,但我找不到对该键的引用。
会不会在配置文件的 ShardMapName 中?
提前致谢。
SQL 架构中的分片键与其用法(在代码中)之间没有明确的 link。
所以在入门示例中,客户和订单 table 都包含一个 CustomerId
列,当我们访问这些 tables 我们确保向 shardMap.OpenConnectionForKey
方法提供相同的 customerId
值,然后在以下查询中将其用于 customerId 列(在 SELECT 和 INSERT 语句中)。
// Looks up the key in the shard map and opens a connection to the shard
using (SqlConnection conn = shardMap.OpenConnectionForKey(customerId, credentialsConnectionString))
{
// Create a simple command that will insert or update the customer information
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"
IF EXISTS (SELECT 1 FROM Customers WHERE CustomerId = @customerId)
UPDATE Customers
SET Name = @name, RegionId = @regionId
WHERE CustomerId = @customerId
ELSE
INSERT INTO Customers (CustomerId, Name, RegionId)
VALUES (@customerId, @name, @regionId)";
cmd.Parameters.AddWithValue("@customerId", customerId);
cmd.Parameters.AddWithValue("@name", name);
cmd.Parameters.AddWithValue("@regionId", regionId);
cmd.CommandTimeout = 60;
// Execute the command
cmd.ExecuteNonQuery();
}
换句话说,当您在 OpenConnectionForKey
调用中提供某个键值时,您有责任确保所有具有该连接的 SQL 查询都限于该键值,否则您最终可能会得到不正确的结果(例如,如果它是一个 SELECT 查询)或位于错误分片上的行(例如,如果它是一个 INSERT 查询)。
可以使用新的行级安全功能解决此安全问题。我们有一个名为 Entity Framework Multi-Tenant Shards that demonstrates how to combine Shard Maps with Row-Level Security. The relevant code is in ElasticScaleContext.cs:
的示例SqlConnection conn = null;
try
{
// Ask shard map to broker a validated connection for the given key
conn = shardMap.OpenConnectionForKey(shardingKey, connectionStr, ConnectionOptions.Validate);
// Set CONTEXT_INFO to shardingKey to enable Row-Level Security filtering
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"SET CONTEXT_INFO @shardingKey";
cmd.Parameters.AddWithValue("@shardingKey", shardingKey);
cmd.ExecuteNonQuery();
return conn;
}
catch (Exception)
{
if (conn != null)
{
conn.Dispose();
}
throw;
}
谢谢你的好问题!