我有一个实体,除了一些常见属性外,它还包含一个扩展属性列表,该列表存储为集合中的 (Name, Value) 字符串对。我可能应该提到,这些扩展属性因实例而异,并且只需要为每个实例列出它们(不会对扩展属性进行任何查询,例如查找具有特定(名称,值)对)。我正在探索如何使用 Windows Azure 表服务来持久化这个实体。对于我现在正在测试的特定方法,我担心随着应用程序遇到更多不同的扩展属性名称,性能可能会随着时间的推移而下降。
如果我将此实体存储在典型的关系数据库中,我可能有两个表来支持此模式:第一个将包含实体标识符及其公共属性,第二个将引用实体标识符并使用 EAV 样式行-建模以存储扩展的 (Name, Value) 对,每行一个。
由于 Windows Azure 中的表已经使用 EAV 模型,因此我正在考虑对我的实体进行自定义序列化,以便存储扩展属性,就好像它们是在实体的编译时声明的一样。我可以使用DataServiceContext提供的 Reading- 和 Writing-Entity 事件来完成此操作。
private void OnReadingEntity(object sender, ReadingWritingEntityEventArgs e)
{
MyEntity Entry = e.Entity as MyEntity;
if (Entry != null)
{
XElement Properties = e.Data
.Element(Atom + "content")
.Element(Meta + "properties");
//select metadata from the extended properties
Entry.ExtendedProperties = (from p in Properties.Elements()
where p.Name.Namespace == Data && !IsReservedPropertyName(p.Name.LocalName) && !string.IsNullOrEmpty(p.Value)
select new Property(p.Name.LocalName, p.Value)).ToArray();
}
}
private void OnWritingEntity(object sender, ReadingWritingEntityEventArgs e)
{
MyEntity Entry = e.Entity as MyEntity;
if (Entry != null)
{
XElement Properties = e.Data
.Element(Atom + "content")
.Element(Meta + "properties");
//add extended properties from the metadata
foreach (Property p in (from p in Entry.ExtendedProperties
where !IsReservedPropertyName(p.Name) && !string.IsNullOrEmpty(p.Value)
select p))
{
Properties.Add(new XElement(Data + p.Name, p.Value));
}
}
}
这是可行的,因为我可以定义扩展属性名称和值的要求,我可以确保它们符合 Windows Azure 表中实体属性的所有标准要求。
那么随着时间的推移,当应用程序遇到数千个不同的扩展属性名称时会发生什么?
以下是我在开发存储环境中观察到的情况:
表容器架构随着每个新名称而增长。我不确定这个模式到底是如何使用的(可能是下一点),但显然这个 xml 文档会随着时间的推移变得非常大。
每当读取一个实例时,传递给 OnReadingEntity 的 xml 包含曾经为任何其他实例存储的每个属性名称的元素(不仅仅是为正在读取的特定实例存储的属性名称)。这意味着实体的检索将随着时间的推移变得更慢。
我应该在生产存储环境中期待这些行为吗?我可以看到这些行为对于大多数表来说是如何可以接受的,因为随着时间的推移,模式大部分是静态的。也许 Windows Azure 表不是为这样使用而设计的?如果是这样,我当然需要改变我的方法。我也愿意接受有关替代方法的建议。