Skip to content

Commit 7a61005

Browse files
committed
Delete orphaned indexed attributes
If an attribute was previously saved as an indexed attribute, but is then saved as an extended attribute, this can cause ambiguity from the database perspective as there will be two (potentially different) values for the same attribute. This ambiguity is addressed by the `SqlTopicRepository` which will always favor extended attributes—but that isn't immediately clear, and especially when evaluating data in the database. This scenario is uncommon. Previously, it was most likely to happen if the configuration for an `AttributeDescriptor` was changed to `IsExtendedAttribute` _after_ indexed values had already been committed to the database. It's more common after I added support for saving arbitrary values (9d848f4), however, since these can go from indexed to extended if their length exceeds the 255 character limit for indexed attributes. Both of these issues can be mitigated by adding all extended attribute keys to the unmatched attributes collection. This collection is used by the `UpdateTopic` stored procedure to delete any unmatched indexed attributes. (In these values aren't deleted due to versioning; instead they are overwritten with a new version with an empty value. The end result is the same, however, since indexed attributes with empty values are no longer returned from the stored procedure.) Technically, we could have incorporated this logic into the `TopicRepositoryBase.GetUnmatchedAttributes()` method. I chose not to, however, because this is somewhat dependent on the business logic of the specific repository. Not all implementations may treat indexed and extended attributes the way SQL does, and thus the way unmatched attributes are handled may vary. If we notice overlap in future implementations we can centralize the logic later, but for now it's safer to treat this as an artifact of the fact that `UpdateTopic` uses `GetUmatchedAttributes()` to overwriting _indexed_ attributes, but not _extended_ attributes. (This is because extended attributes are always rewritten in their entirety in the XML field, and so there's no benefit to overwriting them.) As part of this, to centralize the routine of adding unmatched attributes, the new `addUnmatchedAttribute()` local function was added. It is now used by the processing of both extended attributes as well as `GetUnmatchedAttributes()`. This supports Programmatic Support for Arbitrary Attributes (#19), while also patching a preexisting issue with changing the configuration of attributes.
1 parent 2151a08 commit 7a61005

1 file changed

Lines changed: 16 additions & 2 deletions

File tree

OnTopic.Data.Sql/SqlTopicRepository.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,21 +306,35 @@ public override int Save([NotNull]Topic topic, bool isRecursive = false, bool is
306306
extendedAttributes.Append("<attributes>");
307307

308308
foreach (var attributeValue in GetAttributes(topic, true, null)) {
309+
309310
extendedAttributes.Append(
310311
"<attribute key=\"" + attributeValue.Key + "\"><![CDATA[" + attributeValue.Value + "]]></attribute>"
311312
);
312313
attributeValue.IsDirty = false;
314+
315+
//###NOTE JJC20200502: By treating extended attributes as unmatched, we ensure that any indexed attributes with the same
316+
//value are overwritten with an empty attribute. This is useful for cases where an indexed attribute is moved to an
317+
//extended attribute, as it persists that version history, while removing ambiguity over which record is authoritative.
318+
//This is also useful for supporting arbitrary attribute values, since they may be moved from indexed to extended
319+
//attributes if their length exceeds 255.
320+
addUnmatchedAttribute(attributeValue.Key);
321+
313322
}
314323

315324
extendedAttributes.Append("</attributes>");
316325

317326
/*------------------------------------------------------------------------------------------------------------------------
318-
| Add unmatch attributes
327+
| Add unmatched attributes
319328
\-----------------------------------------------------------------------------------------------------------------------*/
329+
320330
//Loop through the content type's supported attributes and add attribute to null attributes if topic does not contain it
321331
foreach (var attribute in GetUnmatchedAttributes(topic)) {
332+
addUnmatchedAttribute(attribute.Key);
333+
}
334+
335+
void addUnmatchedAttribute(string key) {
322336
var record = attributes.NewRow();
323-
record["AttributeKey"] = attribute.Key;
337+
record["AttributeKey"] = key;
324338
record["AttributeValue"]= null;
325339
attributes.Rows.Add(record);
326340
}

0 commit comments

Comments
 (0)