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: 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. Delegates to
/// for the common traversal logic.
///
/// The context is optional: when omitted, the
/// singleton is used, so call sites read like
/// Client.FindByName("Jane Doe") — no context threading required.
///
public static Client? FindByName(string name, DbContext? db = null)
=> DbBase.Find(c => c.Name == name, db);
}
///
/// 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);
}
}