Project · EF Core companions

EF reservation quote companion

Eight independent BCL checks for proposed reservation arithmetic; no EF, SQL, transaction or storage emulation.

All C# source files below are loaded together in the playground. Files written by a run live in its virtual directory.

Companion.csproj

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup></Project>

Program.cs

Console.WriteLine(QuoteChecks.Run() + " quote checks passed");

Domain/QuoteRules.cs

namespace SharpRune.EfCompanion;
public sealed record QuoteDecision(string Status, long TotalCents);
public static class QuoteRules
{
    public static QuoteDecision Decide(int stock, int quantity, long priceCents)
    {
        if (stock < 0 || quantity <= 0 || priceCents < 0) return new("invalid", 0);
        if (quantity > stock) return new("insufficient", 0);
        return new("accepted", checked(quantity * priceCents));
    }
}

Checks/QuoteChecks.cs

using SharpRune.EfCompanion;
public static class QuoteChecks
{
    public static int Run()
    {
        int count = 0;
        void Check(bool value, string name) { if (!value) throw new InvalidOperationException(name); count++; }
        Check(QuoteRules.Decide(5, 2, 125) == new QuoteDecision("accepted", 250), "accepted quote");
        Check(QuoteRules.Decide(5, 0, 125).Status == "invalid", "zero quantity");
        Check(QuoteRules.Decide(-1, 1, 125).Status == "invalid", "negative stock");
        Check(QuoteRules.Decide(5, 1, -1).Status == "invalid", "negative price");
        Check(QuoteRules.Decide(5, 6, 125).Status == "insufficient", "over stock");
        Check(QuoteRules.Decide(5, 5, 125).TotalCents == 625, "exact stock");
        bool overflow = false; try { QuoteRules.Decide(2, 2, long.MaxValue); } catch (OverflowException) { overflow = true; }
        Check(overflow, "overflow rejected");
        Check(QuoteRules.Decide(1, 1, 0) == new QuoteDecision("accepted", 0), "zero price");
        return count;
    }
}