using System.Collections.ObjectModel; namespace Before; /// /// A client, backed by the database: it derives from and /// holds its orders as a navigation collection. In the "after" situation this /// becomes a plain POCO (no ) with a ClientDto /// carrying its data to the WebApp. /// public class Client : DbBase { /// Display name of the client. public string Name { get; set; } = string.Empty; /// /// Navigation collection of this client's orders. Adding to it performs /// EF-style navigation fix-up (see ). /// public ClientOrders Orders { get; } public Client() { Orders = new ClientOrders(this); } /// /// Convenience lookup: walks the 's tracked entities, /// finds the first whose /// equals . Returns null when no match. /// /// 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. /// 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; } } /// /// An collection that fakes EF's navigation fix-up: when an /// order is added, its back-reference is set to the /// owning client, exactly as EF would wire up the two ends of the relation. /// public sealed class ClientOrders : Collection { private readonly Client _owner; public ClientOrders(Client owner) { _owner = owner; } // Both Add(...) and Insert(...) funnel through InsertItem, so overriding // it covers every way an order can be added to the collection. protected override void InsertItem(int index, Order item) { ArgumentNullException.ThrowIfNull(item); item.Client = _owner; // navigation fix-up: order now knows its client base.InsertItem(index, item); } }