Azure Table 存储:"Parameter count mismatch" 存储 array/list/IEnumerable

Azure Table Storage: "Parameter count mismatch" storing array/list/IEnumerable

我正在尝试编写一个包含集合的简单对象,例如:

public class UserModel
{
    public string FirstName { get; set; }
    public List<string> GroupIDs { get; set; }
}

使用 DynamicTableEntityFlatten 方法,我在提交实体之前通过将 UserModel 对象作为 userModel 传递来设置属性,如下所示:

var entity = new DynamicTableEntity(partitionKey, rowKey);
entity.Properties = TableEntity.Flatten(userModel, new OperationContext());

这难免returns上面提到的错误:

Parameter count mismatch

据我所知,这是由于 here 中描述的 'flatten' 方法造成的。我试过将我的 GroupIDs 对象设置为一个数组、一个列表和 IEnumerable,但没有成功(同样的问题)。

有没有人建议在 Azure Table 存储中对此类对象使用展平方法来提交带有字符串集合的对象?

我想分享我是如何解决这个问题的,因为使用 DynamicTableEntity 不是很清楚;至少我可以轻松找到。如果还有其他建议,我很乐意取消标记此答案。

选项 1:串联

根据您的要求,如果连接结果超过 64KB 限制,这将是一个糟糕的选择。我敢肯定还有其他方法,但是以下方法是对我有用的一种选择。首先,我更改了模型以反映字符串而不是字符串列表:

public List<string> GroupIDs { get; set; } //instead of this

public string GroupIDs { get; set; } //to this

我按如下方式转换了列表:

var groupList = new List<string>{ "123", "456", "789" };
var userObject = new UserModel(
{
    FirstName = "Jason";
    GroupIDs = string.Join(",", groupList);
});

现在 userObject.GroupIDs 属性 是一个字符串,可以像我在原始 post 中显示的那样编写。

选项 2:Table 设计修改

我最终选择了第二条路线,因为通过引用原始对象的 ID 更容易存储和重新水化对象。我必须修改 UserModel 以删除对组的任何引用,然后我需要向其添加一个唯一 ID,如下所示:

public class UserModel
{
    public string FirstName { get; set; }
    public string UserId { get; set; }
}

我创建了一个table,只是为了让原始table引用的组。我首先创建一个 GroupModel 对象来保存我需要引用的 UserId

public class GroupModel
{
    public string UserId { get; set; }
    public string GroupId { get; set; }
    public string GroupName { get; set; }
}

然后我写了一个新的方法来分别处理每个对象如下:

public Interface ITableOps
{
    Task WriteNewUser(UserModel user, List<GroupModel> groups);
}

public class TableOps : ITableOps
{
    public async Task WriteNewUser(UserModel user, List<GroupModel>, groups)
    {
        //...assume user table connection is created

        var entity = new DynamicTableEntity(partitionKey, rowKey);
        entity.Properties = TableEntity.Flatten(user, new OperationContext());
        await userTable.ExecuteAsync(TableOperation.Insert(user));

        //...assume group table connection is created

        groups.ForEach(async g =>
            {
                var groupsEntity = new DynamicTableEntity(user.UserId, Guid.NewGuid().ToString());
                groupsEntity.Properties = TableEntity.Flatten(g, new OperationContext());
                await groupsTable.ExecuteAsync(TableOperation.Insert(groupsEntity));
            });
    }

最后,我写了一个简单的方法来读取Groups的整个分区table。

TableEntity.Flatten 在 SDK 中不支持 ICollection/IEnumerable 类型属性。但是这里的ObjectFlattener API v2.0支持IEnumerable/ICollection等属性。 https://www.nuget.org/packages/ObjectFlattenerRecomposer/

我在 Nuget 包描述中放了一些用法示例,它与使用 TableEntity.Flatten/ConvertBack api 非常相似,但支持所有 属性 类型。