Find falls back to DbBase.Context singleton when no context passed
DbBase.Find<T> now uses db ?? Context, and Client.FindByName's context
parameter becomes optional — call sites read like Client.FindByName("Jane
Doe") without context threading. A null result now overwhelmingly means
"no match"; the residual "no context configured at all" ambiguity is
documented in remarks as part of the ActiveRecord-leak cost this exercise
illustrates.
This commit is contained in:
+10
-6
@@ -25,16 +25,20 @@ public class Client : DbBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience lookup: walks the <paramref name="db"/>'s tracked entities,
|
||||
/// finds the first <see cref="Client"/> whose <see cref="Name"/>
|
||||
/// equals <paramref name="name"/>. Returns <c>null</c> when no match.
|
||||
/// Convenience lookup: finds the first <see cref="Client"/> whose
|
||||
/// <see cref="Name"/> equals <paramref name="name"/>. Returns
|
||||
/// <c>null</c> when no match.
|
||||
///
|
||||
/// This mirrors how an ActiveRecord-style ORM might surface a static
|
||||
/// finder on the domain class itself — it rides the <c>DbContext</c> leak
|
||||
/// from the entity's back-reference. Delegates to
|
||||
/// finder on the domain class itself — it rides the <c>DbContext</c>
|
||||
/// leak from the entity's back-reference. Delegates to
|
||||
/// <see cref="DbBase.Find{T}"/> for the common traversal logic.
|
||||
///
|
||||
/// The context is optional: when omitted, the <see cref="DbBase.Context"/>
|
||||
/// singleton is used, so call sites read like
|
||||
/// <c>Client.FindByName("Jane Doe")</c> — no context threading required.
|
||||
/// </summary>
|
||||
public static Client? FindByName(string name, DbContext? db)
|
||||
public static Client? FindByName(string name, DbContext? db = null)
|
||||
=> DbBase.Find<Client>(c => c.Name == name, db);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,11 +57,22 @@ public class DbBase
|
||||
/// <param name="predicate">Filter applied to candidates of type <typeparamref name="T"/>.
|
||||
/// </param>
|
||||
/// <param name="db">The context whose tracked entities to search.
|
||||
/// When <c>null</c>, falls back to the <see cref="Context"/> singleton —
|
||||
/// so a caller only passes a context explicitly when it must differ from
|
||||
/// the ambient one.
|
||||
/// </param>
|
||||
/// <returns>The first matching entity, or <c>null</c> when no match.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Note the (deliberate, ActiveRecord-style) ambiguity this still leaves:
|
||||
/// a <c>null</c> result means "no match — or no context configured at
|
||||
/// all". The caller cannot distinguish the two; that is part of the cost
|
||||
/// of the static-singleton leak this exercise illustrates.
|
||||
/// </remarks>
|
||||
public static T? Find<T>(Predicate<T> predicate, DbContext? db) where T : DbBase
|
||||
{
|
||||
db ??= Context;
|
||||
|
||||
if (db is null)
|
||||
return default;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user