Table Identity 的存储设计
Table Storage design for Identity
我正在使用 Identity 创建一个 ASP.NET MVC 应用程序,我决定使用 Azure Table 存储,因为它非常便宜且速度快,可以满足我的需求。该应用程序将有两种类型的帐户:单用户帐户和一个所有者的多用户帐户。所以我模拟了这个:
public class User : TableEntity, IUser
{
/// <summary>
/// The Email of the owner of the account
/// </summary>
public string Id { get { return PartitionKey; } set { PartitionKey = value; } }
/// <summary>
/// The Email of the user of the account
/// </summary>
public string UserName { get { return RowKey; } set { RowKey = value; } }
//other fields not relevant
}
不过,我想知道如何使它有效地登录和搜索用户。身份商店有这个:
public async Task<User> FindByIdAsync(string userId)
{
try
{
TableResult operation = await UsersTable.ExecuteAsync(TableOperation.Retrieve<User>(userId, userId));
return operation.Result as User;
}
catch (Exception)
{
return null;
}
}
如果尝试登录的用户是帐户的所有者,这将是单点查询,according to the docs 具有最佳性能。
但是,如果用户不是所有者,则将导致完整的 table 扫描,因为 PartitionKey 将无法对其进行过滤,因此查询的性能最差。
我的另一个想法是让用户成为 PartitionKey,让所有者成为 RowKey,但这会使每次搜索都成为范围查询,并且性能低于单点查询。
我怎样才能最好地设计这个?这是一个新的应用程序,因此没有现有的用户群。
我想提出一些建议(基于我们构建的应用程序,该应用程序也专门使用 Table 存储空间)。
- 引入一个名为
Account
或 Subscription
的新实体。您可以使用 GUID 来唯一标识一个帐户。
- 在用户 table 中连同用户信息(用户 ID、密码等)一起存储帐户信息。因此,在您验证用户身份的任何时候,您都在进行点查询。还将用户的角色(成员或所有者)存储在用户的 table 中。这样做,您就会知道用户是个人用户还是团队的一部分。如果用户是团队的一员,那么该用户在该团队中的角色是什么(所有者或成员)。
- 存储2份用户数据。第一份是你现在使用的。第二个副本实质上将用户与帐户相关联,其中第二个副本的 PartitionKey 是帐户 ID,行键是第一个副本的 PartitionKey。这将帮助您找到特定团队中的用户。
个人用户登录场景
所以个人用户使用他们的 username/password 登录。您检索有关用户的信息,然后根据帐户类型发现该用户是个人用户。
团队负责人登录场景
因此,当团队所有者登录时,根据登录信息,您会发现该用户是团队所有者。如果团队所有者需要查找团队中所有用户的列表,您可以执行另一个查询(这将只是 PartitionKey 查询),它将为您提供有关团队中所有用户的信息。
团队用户登录场景
所以当团队用户登录时,根据登录你会发现该用户是团队用户。由于用户是团队用户,he/she 无需查询 table 即可了解团队中的其他用户。即使他们这样做,您将执行另一个查询(与团队所有者查询相同)以获取团队中的用户列表。
我正在使用 Identity 创建一个 ASP.NET MVC 应用程序,我决定使用 Azure Table 存储,因为它非常便宜且速度快,可以满足我的需求。该应用程序将有两种类型的帐户:单用户帐户和一个所有者的多用户帐户。所以我模拟了这个:
public class User : TableEntity, IUser
{
/// <summary>
/// The Email of the owner of the account
/// </summary>
public string Id { get { return PartitionKey; } set { PartitionKey = value; } }
/// <summary>
/// The Email of the user of the account
/// </summary>
public string UserName { get { return RowKey; } set { RowKey = value; } }
//other fields not relevant
}
不过,我想知道如何使它有效地登录和搜索用户。身份商店有这个:
public async Task<User> FindByIdAsync(string userId)
{
try
{
TableResult operation = await UsersTable.ExecuteAsync(TableOperation.Retrieve<User>(userId, userId));
return operation.Result as User;
}
catch (Exception)
{
return null;
}
}
如果尝试登录的用户是帐户的所有者,这将是单点查询,according to the docs 具有最佳性能。
但是,如果用户不是所有者,则将导致完整的 table 扫描,因为 PartitionKey 将无法对其进行过滤,因此查询的性能最差。
我的另一个想法是让用户成为 PartitionKey,让所有者成为 RowKey,但这会使每次搜索都成为范围查询,并且性能低于单点查询。
我怎样才能最好地设计这个?这是一个新的应用程序,因此没有现有的用户群。
我想提出一些建议(基于我们构建的应用程序,该应用程序也专门使用 Table 存储空间)。
- 引入一个名为
Account
或Subscription
的新实体。您可以使用 GUID 来唯一标识一个帐户。 - 在用户 table 中连同用户信息(用户 ID、密码等)一起存储帐户信息。因此,在您验证用户身份的任何时候,您都在进行点查询。还将用户的角色(成员或所有者)存储在用户的 table 中。这样做,您就会知道用户是个人用户还是团队的一部分。如果用户是团队的一员,那么该用户在该团队中的角色是什么(所有者或成员)。
- 存储2份用户数据。第一份是你现在使用的。第二个副本实质上将用户与帐户相关联,其中第二个副本的 PartitionKey 是帐户 ID,行键是第一个副本的 PartitionKey。这将帮助您找到特定团队中的用户。
个人用户登录场景
所以个人用户使用他们的 username/password 登录。您检索有关用户的信息,然后根据帐户类型发现该用户是个人用户。
团队负责人登录场景 因此,当团队所有者登录时,根据登录信息,您会发现该用户是团队所有者。如果团队所有者需要查找团队中所有用户的列表,您可以执行另一个查询(这将只是 PartitionKey 查询),它将为您提供有关团队中所有用户的信息。
团队用户登录场景
所以当团队用户登录时,根据登录你会发现该用户是团队用户。由于用户是团队用户,he/she 无需查询 table 即可了解团队中的其他用户。即使他们这样做,您将执行另一个查询(与团队所有者查询相同)以获取团队中的用户列表。