Skip to content

Commit 2300e69

Browse files
committed
Introduced new TopicNotFoundException
In order to provide more fine-tuned error handling of cases where a specific topic is requested from the repository, but cannot be found, we are now returning a new `TopicNotFoundException`. As this derives from the previous `TopicRepositoryException`, this should remain compatible with previous exception handlers, while offerring callers more specificity. (Though, it's worth noting, there is a bug in `Load(string topicKey)` which trips on the retrieval of the return code from the `GetTopicId` function if no topic is found. As such, it continues to throw an off-target exception. Further, `Load(int topicKey)` previously threw a `NullReferenceException` if a topic wasn't found, which it shouldn't have been doing. Fortunately, it wasn't publicly documented, and no implementers have been catching it, so we're going to treat this as a bug fix, not a breaking change.)
1 parent 1e9152a commit 2300e69

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

OnTopic.Data.Sql/SqlTopicRepository.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public override Topic Load(string? topicKey = null, bool isRecursive = true) {
8080
\-----------------------------------------------------------------------------------------------------------------------*/
8181
var connection = new SqlConnection(_connectionString);
8282
var command = new SqlCommand("GetTopicID", connection);
83-
int topicId;
83+
var topicId = -1;
8484

8585
command.CommandType = CommandType.StoredProcedure;
8686

@@ -117,6 +117,13 @@ public override Topic Load(string? topicKey = null, bool isRecursive = true) {
117117
connection.Close();
118118
}
119119

120+
/*------------------------------------------------------------------------------------------------------------------------
121+
| Validate results
122+
\-----------------------------------------------------------------------------------------------------------------------*/
123+
if (topicId < 0) {
124+
throw new TopicNotFoundException(topicKey);
125+
}
126+
120127
/*------------------------------------------------------------------------------------------------------------------------
121128
| Return topic
122129
\-----------------------------------------------------------------------------------------------------------------------*/
@@ -177,7 +184,7 @@ public override Topic Load(int topicId, bool isRecursive = true) {
177184
topic = TopicFactory.Create("Root", "Container");
178185
}
179186
else {
180-
throw new NullReferenceException($"Load() was unable to successfully load the topic with the TopicID '{topicId}'");
187+
throw new TopicNotFoundException(topicId);
181188
}
182189
}
183190

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*==============================================================================================================================
2+
| Author Ignia, LLC
3+
| Client Ignia, LLC
4+
| Project Topics Library
5+
\=============================================================================================================================*/
6+
using System;
7+
using System.Data.Common;
8+
using System.Runtime.Serialization;
9+
using OnTopic.Internal.Diagnostics;
10+
11+
namespace OnTopic.Repositories {
12+
13+
/*============================================================================================================================
14+
| CLASS: TOPIC NOT FOUND EXCEPTION
15+
\---------------------------------------------------------------------------------------------------------------------------*/
16+
/// <summary>
17+
/// The <see cref="TopicNotFoundException"/> will be thrown when a topic is requested from the repository, but one cannot be
18+
/// found and there is not a logical fallback.
19+
/// </summary>
20+
/// <remarks>
21+
/// As the <see cref="TopicNotFoundException"/> derives from both <see cref="TopicRepositoryException"/> and <see
22+
/// cref="DbException"/>, it retains compatability with previous exception handling, while offering callers the option of
23+
/// capturing a more specific error for this individual use case.
24+
/// </remarks>
25+
[Serializable]
26+
public class TopicNotFoundException: TopicRepositoryException {
27+
28+
/*==========================================================================================================================
29+
| CONSTRUCTOR: TOPIC NOT FOUND EXCEPTION
30+
\-------------------------------------------------------------------------------------------------------------------------*/
31+
/// <summary>
32+
/// Initializes a new <see cref="TopicNotFoundException" /> instance.
33+
/// </summary>
34+
public TopicNotFoundException() : base() { }
35+
36+
/// <summary>
37+
/// Initializes a new <see cref="TopicNotFoundException" /> instance based on a missing topic ID.
38+
/// </summary>
39+
/// <param name="topicId">The requested <see cref="Topic.Id"/> which cannot be found.</param>
40+
public TopicNotFoundException(int topicId):
41+
base($"The topic {topicId} cannot be found in the repository.") { }
42+
43+
/// <summary>
44+
/// Initializes a new <see cref="TopicNotFoundException" /> instance based on a missing topic ID.
45+
/// </summary>
46+
/// <param name="topicId">The requested <see cref="Topic.Id"/> which cannot be found.</param>
47+
/// <param name="innerException">The reference to the original, underlying exception.</param>
48+
public TopicNotFoundException(int topicId, Exception innerException):
49+
base($"The topic {topicId} cannot be found in the repository.", innerException) { }
50+
51+
/// <summary>
52+
/// Initializes a new <see cref="TopicNotFoundException" /> instance based on a missing topic key.
53+
/// </summary>
54+
/// <param name="topicKey">The requests <see cref="Topic.Key"/> which cannot be found.</param>
55+
public TopicNotFoundException(string? topicKey):
56+
base($"The topic {topicKey} cannot be found in the repository.") { }
57+
58+
/// <summary>
59+
/// Initializes a new <see cref="TopicNotFoundException" /> instance based on a missing topic key.
60+
/// </summary>
61+
/// <param name="topicKey">The requests <see cref="Topic.Key"/> which cannot be found.</param>
62+
/// <param name="innerException">The reference to the original, underlying exception.</param>
63+
public TopicNotFoundException(string? topicKey, Exception innerException):
64+
base($"The topic {topicKey} cannot be found in the repository.", innerException) { }
65+
66+
/// <summary>
67+
/// Instantiates a new <see cref="TopicRepositoryException"/> instance for serialization.
68+
/// </summary>
69+
/// <param name="info">A <see cref="SerializationInfo"/> instance with details about the serialization requirements.</param>
70+
/// <param name="context">A <see cref="StreamingContext"/> instance with details about the request context.</param>
71+
/// <returns>A new <see cref="InvalidKeyException"/> instance.</returns>
72+
protected TopicNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
73+
Contract.Requires(info);
74+
}
75+
76+
} //Class
77+
} //Namespace

0 commit comments

Comments
 (0)