创建具有数组或列表属性的TableEntity?

ser*_*hio 6 azure-table-storage azure-tablequery

我已经在Azure表中存储了一些这样的枚举

pk   rk |    en     fr     de   ...

foo  1  |  'Eune' 'Fune' 'Dune' ...
foo  2  |  'Edoe' 'Fdoe' 'Ddoe' ...

bar  1  |  'Unee' 'Unef' 'Trid' ...
bar  2  |  'Diee' 'Dief' 'Died' ...
bar  3  |  'Trie' 'Tref' 'Trid' ...
Run Code Online (Sandbox Code Playgroud)

enfrde等...是语言代码,并分别在表中的列名。

TableEntity应该创建哪种类型才能正确加载它

public class FooEntity : TableEntity
{
    public Dictionary<string, string> Descriptions {get; set} // ?
}
Run Code Online (Sandbox Code Playgroud)

然后像myFoo["fr"]... 那样使用它们吗?

说我有英文GUI,我需要显示一个Foo带有Eune/ Edoe作为选择值的选择。

Har*_*pta 8

我的回答将肇兴的方法扩展为将复杂实体属性写入JSON并将其持久化到Azure CosmosDB。

但是,在setter中的字符串和对象之间进行序列化会导致以下问题:

  1. 例如,如果要在字典DicProperty中添加或删除某个项目,则不会调用该设置程序,因为您尚未修改字典,但已修改其内容。同样,在更复杂的用例中,如果您对序列化自定义对象或类感兴趣,则修改类的成员将不会触发设置器。当实体提交到CloudTable时,这可能导致数据丢失。
    1. 如果确实选择在复杂属性上实现类似INotifyPropertyChanged的操作(通过使用某种形式的ObservableCollection或自己完成事件通知),则最终会导致序列化和反序列化的次数过多。这也是整个模型中太多代码无法使用的方式。

相反,我覆盖了TableEntity的WriteEntity和ReadEntity方法以编写自定义序列化和反序列化代码,这些代码仅在从CloudTable检索实体或将其提交给实体时才调用-因此每次检索,更新操作等仅一次。

下面的代码。我已经说明了一个更复杂的示例,其中我的TableEntity包含一个类,而该类又包含一个字典。

public class MeetingLayoutEntity : TableEntity
{
    /// <summary>
    ///  Extends TableEntity, the base class for entries in Azure CosmosDB Table tables. 
    /// </summary>
    public MeetingLayoutEntity() { }

    public MeetingLayoutEntity(MeetingLayout layout, string partition, string meetingId)
    {
        this.Layout = layout;
        this.PartitionKey = partition;
        this.RowKey = meetingId;
    }

    // Complex object which will be serialized/persisted as a JSON.
    [IgnoreProperty]
    public MeetingLayout Layout { get; set; }

    public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
    {
        // This line will write partition key and row key, but not Layout since it has the IgnoreProperty attribute
        var x = base.WriteEntity(operationContext);

        // Writing x manually as a serialized string.
        x[nameof(this.Layout)] = new EntityProperty(JsonConvert.SerializeObject(this.Layout));
        return x;
    }

    public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
    {
        base.ReadEntity(properties, operationContext);
        if (properties.ContainsKey(nameof(this.Layout)))
        {
            this.Layout = JsonConvert.DeserializeObject<MeetingLayout>(properties[nameof(this.Layout)].StringValue);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

了解有关ReadEntityWriteEntity的更多信息。


Zha*_*oft 7

Azure存储表不支持将数组,列表或字典作为实体属性。您可以在此处找到所有受支持的属性类型(“属性类型”部分)。

但是,您可以考虑将数组/列表/字典序列化为字符串属性,并在TableEntity类中使用[IgnoreProperty]属性声明一个属性,以将序列化的字符串转换回数组/列表/字典。

public class MyEntity : TableEntity
{
    public string DicPropertyRaw { get; set; }

    [IgnoreProperty]
    public Dictionary<string, string> DicProperty
    {
        get
        {
            return Deserialize(DicPropertyRaw);
        }

        set
        {
            DicPropertyRaw = Serialize(value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)