是否可以为 Azure 表存储提供非派生 POCO?
换句话说,一个不派生自TableEntity
或不实施的 POCO ITableEntity
?
必须拥有一个依赖于接口或基类的模型似乎是一个倒退,因为这会导致链中的引用向上泄漏——我无法在另一个层中设置模型,而无需了解 Azure 存储接口还是基类!
是否可以为 Azure 表存储提供非派生 POCO?
换句话说,一个不派生自TableEntity
或不实施的 POCO ITableEntity
?
必须拥有一个依赖于接口或基类的模型似乎是一个倒退,因为这会导致链中的引用向上泄漏——我无法在另一个层中设置模型,而无需了解 Azure 存储接口还是基类!
看一下DynamicTableEntity
(ctrl+f)。它可用于查询和插入实体。
使用这种类型,您不会在域模型中引入任何依赖项,但是您必须自己将 POCO 转换为 DynamicTableEntity - 如果您愿意使用自定义界面标记您的 POCO,则此过程可以轻松自动化并编写一个映射器(基本上你只需要一个属性字典+需要知道哪些是分区/行键)。
不能只在 Azure 表存储中保存任何实体的原因是它需要知道哪个属性充当分区键,哪个属性充当行键。必须在“较低级别”上工作的好处DynamicTableEntity
是您可以创建仅返回属性子集的查询,从而减少资源消耗。这对您的情况可能有益,也可能无益。
看看我实现并放入 Nuget 的包: https ://www.nuget.org/packages/ObjectFlatenerRecomposer/
它也被添加到下一个版本的 Azure 存储 SDK 中: https ://github.com/Azure/azure-storage-net/pull/337/files
描述:
提供将复杂对象展平到 EntityProperty 字典中的功能,以及从展平的属性字典中重构原始复杂对象的功能。一种用法是 API 允许将任何具有嵌套属性的复杂对象以扁平形式写入 Azure 表存储,这通常无法通过使用 Azure 存储客户端 SDK 实现。
2.0 版现在还支持将IEnumerable
类型属性(如列表、数组、字典)写入和读取到 Azure 表存储。
博客:https ://doguarslan.wordpress.com/2016/02/03/writing-complex-objects-to-azure-table-storage/
用法:
//Flatten object and convert it to EntityProperty Dictionary
Dictionary<string, EntityProperty> flattenedProperties = ObjectFlattenerRecomposer.Flatten(complexObject);
// Create a DynamicTableEntity and set its PK and RK
DynamicTableEntity dynamicTableEntity = new DynamicTableEntity(partitionKey, rowKey);
dynamicTableEntity.Properties = flattenedProperties;
// Write the DynammicTableEntity 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.
Imagine original complexObject was of type Order.
Order order = ObjectFlattenerRecomposer.ConvertBack<Order>(entity.Properties);
首先,除了 TableEntity 和 ITableEntity 之外,还有另一种选择,即使用 DataServiceKey 属性来装饰你的类,如下例所示:
[DataServiceKey("PartitionKey", "RowKey")]
public class MyEntity
{
public string PartitionKey {get; set;}
public string RowKey {get; set;}
public DateTime Timestamp {get; set;}
//other properties
}
但是,这并不能真正解决您不想将 Azure 实现泄漏到模型类中的问题。在这种情况下,我认为您可能希望考虑使用像LOKAD Fat Entities这样的包装器实现。Lokad 会将模型对象的序列化/反序列化处理成一个包装器,而该包装器又存储在表存储中。然而,Lokad 的一个缺点是您的对象在存储中变得不透明,您无法使用诸如Azure Storage Explorer之类的东西浏览它们。