v5.0.0
OnTopic 5.0.0 is a major release primarily focused on reliability and tidying up the interface. It includes a significant number of breaking changes—though only a handful of them will affect most implementers.
New Features
- Metapackage: Established
OnTopic.All
metapackage which includes a reference to all of the core packages and implementations (c15bf2e). - SourceLink: Configured
SourceLink
with references to GitHub commits so that packages can be properly debugged by implementers (f7fb979). - IntelliSense: The NuGet packages now include the XML documentation, thus allowing implementers to benefit from IntelliSense annotations in Visual Studio (219ece4).
- Lookup Fallback Types: Allow multiple fallback types to be defined when calling
ITypeLookupService.Lookup()
(ab4253d). - Topic References: Introduced support for keyed topic references via
Topic.References
, with full support for enforcing business logic (31144cc). - Full Versioning Support: Introduced versioning support for
Relationships
andTopicReferences
, in addition to the previous support for versioning inAttributes
andExtendedAttributes
(0e808ea). - Repository Caching: Established a
ITopicRepository.Refresh()
interface (3d51b14),SqlTopicRepository.Refresh()
implementation (6dbf973), as well as aGetTopicUpdates
stored procedure (0f36947) to allow occasional cache updates without needing to reload the entire topic graph (164de05). - Contextual Loading: When calling
ITopicRepository.Load()
, an optionalreferenceTopic
can now be passed; this allows individual topics or topic branches to be loaded, while still being able to connect relationships and topic references to elsewhere in the topic graph (180526e). It can also be used to update topics already in the topic graph. - Resolve Associations:
TopicRepository.Save()
will now recurse overChildren
and attempt to resolve unresolved associations, such as relationships and topic references (fdd0025, e703de5); previously, this had to be implemented by each individual implementation. - Repository Events:
ITopicRepository
now supports theTopicLoaded
andTopicSaved
events, in addition to the previousTopicRenamed
,TopicMoved
andTopicDeleted
events (37b38f5). - C# 9.0 Records: Introduced support for mapping C# 9.0 records with
init
setters in the topic mapping services (75dea66, 145c2a4) and updated all view models and binding models from read/write classes to C#'s new read-only, immutablerecord
types (10d0652). - Core Attributes:
TopicKey
,ContentType
, andParentID
are now first-class columns in theTopics
table (c50f44d), greatly simplifying querying for the core attributes. - SQL Unit Tests: Introduced unit tests for stored procedures and functions for SQL Server database schema (91e3fe4) as well as for the
SqlDataReader
extension methods used bySqlTopicRepository
(b91c292), thus offering far more assurances over the correctness and regression testing.
Bug Fixes
- Post-Exception Business Logic Enforcement: If an exception occurs while enforcing business logic on
Topic.Attributes
, the request will be de-registered, thus ensuring any subsequent attempts to set an item with the same key will have business logic enforced (1b5dd5b). Previously, the exception could prevent that process from being completed, thus introducing a potential loophole during subsequent actions. - Track Deleted Attributes: Ensured that
AttributeCollection.Clear()
correctly marked the collection asIsDirty()
, if appropriate, by accounting anyDeletedAttributes
(ce3cc43). - Track Attribute Reversions: Ensured that all modified
AttributeRecord
instances in aTopicRepositoryBase.Rollback()
operation were correctly marked asIsDirty
, thus ensuring they would be properlySave()
d (e77d8eb). - Allow Duplicate Topic Keys in Relationships: The
Topic.Relationships
collection now allows relationships to different topics with the sameTopic.Key
(66ccd9d). Previously, this used aKeyedTopicCollection
, which artificially restricted it to relationships with a uniqueKey
. - Allow Duplication Topic Keys in
FindAll()
: Fixed a bug in theTopic.FindAll()
extension methods which prevented it from returning multiple topics which the sameKey
, even if they represented different entities (75f6369). - Track Version in Reversion: Fixed bug in the
GetTopicVersion
stored procedure which resulted in theVersion
column not being returned forAttributes
orExtendedAttributes
, and thus theAttributeRecord.LastModified
not being properly updated during e.g. aRollback()
(622d575). In practice, this didn't harm anything, but it prevented removal of legacy schema validation which explicitly looked for theVersion
column. - Map Overriden Members and Overloaded Methods: Resolved an issue where the
MemberInfoCollection<T>
—used by the topic mapping services—would throw an exception if an overloaded or overridden member was present on a type (75dea66). Now, it will simply defer to the first or most derived instance of a member, and ignore all others. This enables support for C# 9.0 records, which have an implicit compiler-injected override, and is also a logical default for most scenarios where this might occur. - Allow Multiple Roots: Fixed bug where calling the
CreateTopic
orMoveTopic
stored procedures with anull
@ParentID
would result in a corrupted hierarchy (500ca09). This isn't an expected use case, but we obviously want to make sure there's no risk of corrupting the hierarchy if it does occur. - Stored Procedure Errors: Fixed the
RAISERROR()
calls in theMoveTopic
stored procedure; these weren't working correctly due to a formatting bug (bfdec1c).
Breaking changes
For a quick summary of all renamed and removed types, members, and methods, see #27.
- .NET Framework Support: Removed support for .NET Standard 2.0 and, thus, .NET Framework; this effectively ends support for OnTopic-WebForms, OnTopic-MVC, and OnTopic-Editor-WebForms (b3ba1a0).
Topic.DerivedTopic
: RenamedTopic.DerivedTopic
to the more semantically accurateTopic.BaseTopic
(2486ab2). This breaks not only calls toTopic.DerivedTopic
, but also database records for e.g.ReferenceKey
s storing theDerivedTopic
value. The OnTopic 5.x database migration script addresses the data aspects of the migrations.- Immutable View Models: Changed all view models and binding models from read/write classes to C#'s new read-only, immutable
record
types (10d0652). This necessitates that all adopters that rely on these migrate any derived types from classes to records. - Keyed Topic Collections: Renamed
TopicCollection
classes (such asTopicCollection<T>
,ReadOnlyTopicCollection
) toKeyedTopicCollection
(e.g.,KeyedTopicCollection<T>
,ReadOnlyKeyedTopicCollection
) to better communicate that the items are indexed and, thus, must have a unique key, even if they represent different entities (826b93c). - Attribute Collection: Renamed
AttributeValueCollection
toAttributeCollection
, andAttributeValue
toAttributeRecord
(f51407a). TopicRelationshipMultiMap
: TheRelatedTopicCollection
andNamedTopicCollection
used byTopic.Relationships
have been replaced withTopicRelationshipMultiMap
(57ff3f9, 7129289),ReadOnlyTopicMultiMap
(eb5c1c3), andTopicMultiMap
(d049ea9). Care was taken to maintain the overall interface. The interface for calls to the underlying collections, however, will have changed (66ccd9d). Most notably, all write operations must now go throughSetValue()
,Remove()
, orClear()
. In addition, for callers iterating over the relationships, the relationship key is nowKey
notName
, the topics are now stored under aValues
property, and the methods now require a fullTopic
reference, instead of just aTopic.Key
(0d9dcd5).GetValue()
Syntax: Renamed(ReadOnly)KeyedTopicCollection<T>.GetTopic()
toGetValue()
(6674c7d); onTopicRelationshipMultiMap
(i.e.,Topic.Relationships
), renamedGetAllTopics()
,GetTopics()
,RemoveTopic()
, andClearTopics()
toGetAllValues()
,GetValues()
,Remove()
, andClear()
for consistency with other collections, and especially theTrackedRecordCollection
used byAttributeCollection
andTopicRelationshipCollection
(34a8c52).OnTopic.Lookup
namespace: Consolidated allITypeLookupService
implementations into a newOnTopic.Lookup
namespace (f80e084).Load()
by Unique Key: ModifiedLoad(topicKey)
to instead expect a fully-qualifiedUniqueKey
(e.g.,Root:Web:Products
); as part of that, renamed thetopicKey
parameter touniqueKey
to disambiguate usage (4c3d30f).- Mapping Attributes: Renamed
[Relationship()]
to[Collection()]
(f84ae66),[Follow()]
to[Include()]
(7c150d8),RelationshipType
toCollectionType
(1daf799), andRelationships
toAssociationTypes
(78600fd) as part of a broader effort to establish a more consistent and unified nomenclature that distinguishes between topic associations and specific types of associations, such asTopic.Relationships
,Topic.References
, orTopic.BaseTopic
(b01216e). - Filter by Content Type: The
[FilterByAttribute()]
attribute continues to operate as it previously did, but can no longer be used to filter byContentType
since content type is no longer stored inTopic.Attributes
(4a9f5b7); instead, use the new[FilterByContentType()]
attribute (105cfdd). IfContentType
is used with[FilterByAttribute()]
, anArgumentException
will be thrown (c68040a). IRouteBuilder
Support: Removed (deprecated) support forIRouteBuilder
extension methods in ASP.NET Core; implementers should use end point routing viaIEndpointRouteBuilder
instead (6be993b, 19612ac).NavigationViewModel
: ReplacedCurrentKey
withCurrentWebPath
; updated theINavigationTopicViewModel<T>
'sIsSelected()
method to expect awebPath
parameter instead of auniqueKey
parameter (3e68b16).- Core Attributes: Added
@Key
and@ContentType
to theCreateTopic
andUpdateTopic
stored procedures (a74389d); removedTopicKey
,ContentType
, andParentID
from theAttributes
table; they are now in theTopics
table (c50f44d).
Improvements
- Default Attribute Values: The
AttributeCollection
extension methods, such asGetBoolean()
andGetDateTime()
, no longer require that adefaultValue
parameter be defined; if it is omitted, the default value for each datatype (e.g.,false
forGetBoolean
) will be used (a79a0b1). TrackedRecordCollection<>
: Established newTrackedRecordCollection<>
and baseTrackedCollection<>
to handleIsDirty
tracking and enforcement of business logic in keyed collections associated with a particular topic; this is now the base class for bothAttributeCollection
andTopicReferenceCollection
(8b9ae46).Topic.IsDirty()
: IntroducedTopic.IsDirty()
method to aid in state tracking; optionally, this can optionally callAttributeCollection.IsDirty()
andRelatedTopicCollection.IsDirty()
via thecheckCollections
parameter (a8feb6d, f7d36f0).Topic.MarkClean()
: IntroducedMarkClean()
method toTopic
(28ea6ea, 48e8ed4) andRelatedTopicCollection
(c37934b).ITrackDirtyKeys
: Introduced a newITrackDirtyKeys
interface to standardize the implementation ofIsDirty()
andMarkClean()
betweenTopic
(f7d36f0),Topic.Attributes
,Topic.Relationships
, andTopic.References
(c757dd3).
The above is just a high-level summary of the highest impact features, changes, and improvements. For complete release notes, see Pull Request #28.