使用TableServiceEntity将复杂对象插入到azure表中

时间:2013-11-10 01:24:10

标签: c# azure entity azure-table-storage

我正在考虑将整个复杂对象添加到表中。来自良好的老式SQL方法,我显然将其分为表格,但我正在尝试不同的方法。所以基本上我有一个对象,它由一个嵌套类(当你反序列化一个json集合时得到的东西)组成,它有通常的Customer,Business和InvoiceItems列表。

public class Business
{
    public string _id { get; set; }
    public string name { get; set; }
    public string street_1 { get; set; }
    public string street_2 { get; set; }
    public string town { get; set; }
    public string county { get; set; }
    public string postcode { get; set; }

 //other fields as needed
}

public class Customer
{
    public string _id { get; set; }
    public string name { get; set; }
    public string street_1 { get; set; }
    public string street_2 { get; set; }
    public string town { get; set; }
    public string county { get; set; }
    public string postcode { get; set; }

    //other fields as needed
 }

public class InvoiceItems
{
    public string item_id { get; set; }
    public string price_per_unit { get; set; }
    public string quanity { get; set; }
    public string date { get; set; }
}

public class WholeObject
{

    public Customer customer { get; set; }
    public Business address { get; set; }
    public List<InvoiceItems> items { get; set; }
}

(真正的样本课程)

除了1MB大小之外是否有任何限制将其插入表中?我已经阅读了TableServiceEntity,它应该映射C#对象,但它会处理吗? 在这个阶段,这是一个非常假设的问题,因为我实际上并没有尝试对其进行编码。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:15)

复杂属性不会保存到表存储中。只能保留标准数据类型的子集。请查看此链接以获取有关支持的数据类型的更多信息:http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx(查看“属性类型”部分)

但是,你想做的事情是可能的,只是稍微难以实现。这有两种方法可以做到:

  • 在WholeObject类上公开CustomerSerialized,AddressSerialized和ItemsSerialized属性。让这些属性将其关联的复杂对象序列化/反序列化为字节数组,json或xml。这种方法有两个缺点:a)即使你只需要Customer对象,你也总是从azure表存储中加载完整的对象树; b)每个对象的每个属性限制为64kb,因此最好确保InvoiceItems集合适合64kb序列化

  • 提出一个PartitionKey / RowKey模式,允许您将所有类型的相关对象保存为单个实体,但使用PartitionKey / Rowkey指示它们之间的关系。这将允许您独立地获取完整对象树或单个子对象。这种方法没有第一种方法的两个缺点,但在实施时肯定是复杂的一面。它还限制了您将PartitionKey / RowKey调整为其他业务需求的能力。我为一家大型电子商务公司做了这种方法取得了很大的成功 在我的项目中,所有实体(root和child)的PartitionKey被映射到&#34; WholeObject&#34;的ID。而RowKey由ParentObjectID,ChildObjectID和ChildObjectType的串联组合组成。当需要检索WHoleObject中的所有对象时,只需对PartitionKey发出一个查询,否则使用PartitionKey和RowKey的一部分来获取某些类型的对象(即:所有地址)或PartitionKey和完整的RowKey来获取个体实体。这种方法支持无限深度的对象树结构,但是,一旦实体数量超过100,将对象存储在一个事务中就很头疼了。

HTH

答案 1 :(得分:13)

我遇到了类似的问题并实现了一个通用对象flattener / recomposer API,它将复杂的实体展平为扁平get_last_n_digits(to_bin(254,S) ; 词典,并以{{1}的形式将它们写入表存储}。

然后,相同的API将从EntityProperty的{​​{1}}字典重新组合整个复杂对象。

查看:https://www.nuget.org/packages/ObjectFlattenerRecomposer/

<强>用法:

DynamicTableEntity

从那时起,我与azure团队合作,并将此功能集成到Azure Storage SDK 8.0版。

一个重要的注意事项是Azure SDK中的API不支持EntityPropertyDynamicTableEntity类型属性。但是如果您在上面的链接中获得了nuget包v2,那么您几乎可以将任何对象写入Azure表存储,包括具有可枚举的集合类型属性的对象。

https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.table.tableentity.flatten.aspx

https://msdn.microsoft.com/en-us/library/azure/mt775432.aspx

我还在SDK版本8.2.0中添加了//Flatten object of type Order) and convert it to EntityProperty Dictionary Dictionary<string, EntityProperty> flattenedProperties = EntityPropertyConverter.Flatten(order); // Create a DynamicTableEntity and set its PK and RK DynamicTableEntity dynamicTableEntity = new DynamicTableEntity(partitionKey, rowKey); dynamicTableEntity.Properties = flattenedProperties; // Write the DynamicTableEntity to Azure Table Storage using client SDK //Read the entity back from AzureTableStorage as DynamicTableEntity using the same PK and RK DynamicTableEntity entity = [Read from Azure using the PK and RK]; //Convert the DynamicTableEntity back to original complex object. Order order = EntityPropertyConverter.ConvertBack<Order>(entity.Properties); 类,以简化使用。只需将复杂的实体传递给它的构造函数,它就会透明地处理在写入和读取时展平/转换复杂对象。 https://github.com/Azure/azure-storage-net/blob/master/Lib/Common/Table/TableEntityAdapter.cs