Yak: csharp after situation (Yak 02) — plain domain + DTOs + mappers
After/: plain Client/Order (no DbBase), ClientDto/OrderDto records carrying the relations both ways, hand-written Mappers with a reference-identity cache for the back-reference cycle, DbContext with explicit Save(domain) via shadow entities (flipped dependency), and a WebApp that consumes only DTOs. AfterTests cover the 7 required behaviours; full solution builds with 0 warnings, 26/26 tests pass.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace After;
|
||||
|
||||
/// <summary>
|
||||
/// A plain domain object — the "after" shape of the exercise: no
|
||||
/// <see cref="DbBase"/> inheritance, no knowledge of <see cref="DbContext"/>.
|
||||
/// Its data travels to the WebApp as a <see cref="ClientDto"/>; persisting it
|
||||
/// is an explicit act of the context, not an inherited capability.
|
||||
/// </summary>
|
||||
public class Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Primary key as a plain value: fresh objects have
|
||||
/// <see cref="Guid.Empty"/> until a <see cref="DbContext"/> explicitly
|
||||
/// saves them (which copies a generated id in). A plain field — it is not
|
||||
/// a persistence concept leaking into the domain.
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>Display name of the client.</summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Navigation collection of this client's orders, with EF-style
|
||||
/// navigation fix-up (see <see cref="ClientOrders"/>).
|
||||
/// </summary>
|
||||
public ClientOrders Orders { get; }
|
||||
|
||||
public Client()
|
||||
{
|
||||
Orders = new ClientOrders(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="Order"/> collection that fakes EF's navigation fix-up: when an
|
||||
/// order is added, its <see cref="Order.Client"/> back-reference is set to the
|
||||
/// owning client, exactly as EF would wire up the two ends of the relation.
|
||||
/// </summary>
|
||||
public sealed class ClientOrders : Collection<Order>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user