From c21c6416cf319c4d8f61ddd0c37e51c9638a4de2 Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Mon, 14 Sep 2026 20:45:12 +0100 Subject: [PATCH] =?UTF-8?q?Add=20DbBase.Find=20static=20generic=20finde?= =?UTF-8?q?r=20(yak:=20Console=20app=20for=20Before=20(ActiveRecord-style)?= =?UTF-8?q?=20>=20=E2=97=8B=20Add=20DbBase.Find=20static=20generic)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Before/Client.cs | 14 +++----------- src/Before/DbBase.cs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/Before/Client.cs b/src/Before/Client.cs index 7beb365..c485dbe 100644 --- a/src/Before/Client.cs +++ b/src/Before/Client.cs @@ -31,19 +31,11 @@ public class Client : DbBase /// /// This mirrors how an ActiveRecord-style ORM might surface a static /// finder on the domain class itself — it rides the DbContext leak - /// from the entity's back-reference. + /// from the entity's back-reference. Delegates to + /// for the common traversal logic. /// public static Client? FindByName(string name, DbContext? db) - { - if (db is null) - return null; - - foreach (var e in db.Tracked) - if (e is Client c && c.Name == name) - return c; - - return null; - } + => DbBase.Find(c => c.Name == name, db); } /// diff --git a/src/Before/DbBase.cs b/src/Before/DbBase.cs index d6b97b0..b4120fa 100644 --- a/src/Before/DbBase.cs +++ b/src/Before/DbBase.cs @@ -26,4 +26,34 @@ public class DbBase /// (including the WebApp, and the tests) can only read it. /// public DbContext? DbContext { get; internal set; } + + /// + /// Generic ActiveRecord-style finder: walks the 's tracked entities, looks for the first whose runtime type matches + /// and satisfies + ///. + /// + /// This static generic rides the DbContext leak just like + /// , but works for any subtype without each entity needing its own hand-written finder. + /// + /// Entity type to find (must derive from ). + /// + /// Filter applied to candidates of type . + /// + /// The context whose tracked entities to search. + /// + /// The first matching entity, or null when no match. + /// + public static T? Find(Predicate predicate, DbContext? db) where T : DbBase + { + if (db is null) + return default; + + foreach (var e in db.Tracked) + if (e is T candidate && predicate(candidate)) + return candidate; + + return default; + } } \ No newline at end of file