Add DbBase.Find<T> static generic finder (yak: Console app for Before (ActiveRecord-style) > ○ Add DbBase.Find<T> static generic)
This commit is contained in:
+3
-11
@@ -31,19 +31,11 @@ public class Client : DbBase
|
|||||||
///
|
///
|
||||||
/// This mirrors how an ActiveRecord-style ORM might surface a static
|
/// This mirrors how an ActiveRecord-style ORM might surface a static
|
||||||
/// finder on the domain class itself — it rides the <c>DbContext</c> leak
|
/// finder on the domain class itself — it rides the <c>DbContext</c> leak
|
||||||
/// from the entity's back-reference.
|
/// from the entity's back-reference. Delegates to
|
||||||
|
/// <see cref="DbBase.Find{T}"/> for the common traversal logic.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Client? FindByName(string name, DbContext? db)
|
public static Client? FindByName(string name, DbContext? db)
|
||||||
{
|
=> DbBase.Find<Client>(c => c.Name == name, 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -26,4 +26,34 @@ public class DbBase
|
|||||||
/// (including the WebApp, and the tests) can only read it.
|
/// (including the WebApp, and the tests) can only read it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DbContext? DbContext { get; internal set; }
|
public DbContext? DbContext { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generic ActiveRecord-style finder: walks the <paramref name="db"/
|
||||||
|
/// />'s tracked entities, looks for the first whose runtime type matches
|
||||||
|
/// <typeparamref name="T"/> and satisfies <paramref name="predicate"/>
|
||||||
|
///.
|
||||||
|
///
|
||||||
|
/// This static generic rides the <c>DbContext</c> leak just like
|
||||||
|
/// <see cref="Client.FindByName"/>, but works for any <see cref="DbBase"
|
||||||
|
/// /> subtype without each entity needing its own hand-written finder.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Entity type to find (must derive from <see cref="DbBase"/>).
|
||||||
|
/// </typeparam>
|
||||||
|
/// <param name="predicate">Filter applied to candidates of type <typeparamref name="T"/>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="db">The context whose tracked entities to search.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The first matching entity, or <c>null</c> when no match.
|
||||||
|
/// </returns>
|
||||||
|
public static T? Find<T>(Predicate<T> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user