Throw ObjectNotFoundException from FindRequired; add run-console wrappers

- DbBase.FindRequired / Client.FindByNameRequired now throw the
  domain-specific ObjectNotFoundException (NHibernate lineage; Rails
  equivalent: ActiveRecord::RecordNotFound) on a lookup miss; the
  no-context case stays InvalidOperationException (configuration error)
- Console demo catches the new type; tests (18)/(21) assert it,
  (19)/(23) keep InvalidOperationException with rationale comments
- scripts/run-console.sh delegates to dotnet.sh; run-console.ps1 is
  the Windows/PowerShell counterpart (mise-first, repo-root cd)

Yak: objectnotfoundexception-run-console-wrappers-3p8b
This commit is contained in:
2026-09-14 22:39:21 +01:00
parent 4b6e6f5a00
commit ec9586c316
8 changed files with 104 additions and 17 deletions
+10 -4
View File
@@ -358,7 +358,8 @@ public class BeforeTests
}
// ---------------------------------------------------------------------
// (18) DbBase.FindRequired<T> throws when no match is found.
// (18) DbBase.FindRequired<T> throws ObjectNotFoundException when no match
// is found (the domain-specific lookup miss, not a BCL exception).
// ---------------------------------------------------------------------
[Fact]
public void DbBase_FindRequired_T_throws_when_no_match()
@@ -366,7 +367,7 @@ public class BeforeTests
var db = new DbContext();
db.Attach(new Client { Name = "Acme" });
var ex = Assert.Throws<InvalidOperationException>(() =>
var ex = Assert.Throws<ObjectNotFoundException>(() =>
DbBase.FindRequired<Client>(c => c.Name == "Nobody", db, "name == Nobody"));
Assert.Contains("Nobody", ex.Message);
@@ -376,6 +377,9 @@ public class BeforeTests
// ---------------------------------------------------------------------
// (19) DbBase.FindRequired<T> throws with a useful message when no context is
// configured (both explicit null and singleton null).
//
// Deliberately InvalidOperationException, not ObjectNotFoundException:
// a missing context is a configuration error, not a lookup miss.
// ---------------------------------------------------------------------
[Fact]
public void DbBase_FindRequired_T_throws_when_no_context_configured()
@@ -405,7 +409,8 @@ public class BeforeTests
}
// ---------------------------------------------------------------------
// (21) Client.FindByNameRequired throws when no match — message includes name.
// (21) Client.FindByNameRequired throws ObjectNotFoundException when no
// match — message includes name.
// ---------------------------------------------------------------------
[Fact]
public void Client_FindByNameRequired_throws_with_name_when_not_found()
@@ -413,7 +418,7 @@ public class BeforeTests
var db = new DbContext();
db.Attach(new Client { Name = "Acme Corp" });
var ex = Assert.Throws<InvalidOperationException>(() =>
var ex = Assert.Throws<ObjectNotFoundException>(() =>
Client.FindByNameRequired("Nobody", db));
Assert.Contains("Nobody", ex.Message);
@@ -445,6 +450,7 @@ public class BeforeTests
// ---------------------------------------------------------------------
// (23) Client.FindByNameRequired throws with a useful message when the
// singleton is not configured (no arg, no singleton).
// Stays InvalidOperationException: configuration error, not a miss.
// ---------------------------------------------------------------------
[Fact]
public void Client_FindByNameRequired_throws_with_context_hint_when_singleton_null()