Tutorial

4.7 Register the context and create its schema

Program.cs:

using Microsoft.EntityFrameworkCore;
using Shopfront.Data;
using Shopfront.Failures;
using Shopfront.Inventory;
using Shopfront.Payments;
using Shopfront.Trains.PlaceOrder;
using Trax.Core.Exceptions;
using Trax.Effect.Data.Postgres.Extensions;
using Trax.Effect.Data.Services.DomainContext;
using Trax.Effect.Extensions;
using Trax.Effect.JunctionProvider.Logging.Extensions;
using Trax.Effect.Provider.Parameter.Extensions;
using Trax.Effect.Services.FailureClassifier;
using Trax.Mediator.Extensions;
 
var builder = WebApplication.CreateBuilder(args);
 
var connectionString =
    builder.Configuration.GetConnectionString("Shopfront")
    ?? throw new InvalidOperationException("ConnectionStrings:Shopfront is not set.");
 
builder.Services.AddDomainDataContext<IShopfrontDbContext, ShopfrontDbContext>(options =>
    options.UseNpgsql(connectionString)
);
builder.Services.AddScoped<Catalogue>();
builder.Services.AddSingleton<IPaymentProvider, FakePaymentProvider>();
builder.Services.AddSingleton<IFailureClassifier, ShopfrontFailureClassifier>();
 
builder.Services.AddTrax(trax =>
    trax.AddEffects(effects =>
            effects
                .UsePostgres(connectionString)
                .SaveTrainParameters()
                .AddJunctionLogger(serializeJunctionData: true)
        )
        .AddMediator(typeof(Program).Assembly)
);
 
var app = builder.Build();
 
await app.Services.EnsureSchemaCreatedAsync<ShopfrontDbContext>();
 
app.MapPost(
    "/orders",
    async (PlaceOrderInput input, IPlaceOrderTrain train, CancellationToken cancellationToken) =>
    {
        try
        {
            return Results.Ok(await train.Run(input, cancellationToken));
        }
        catch (TrainException ex)
        {
            return Results.UnprocessableEntity(ex.Message);
        }
    }
);
 
await app.RunAsync();

AddDomainDataContext registers a pool of contexts and resolves IShopfrontDbContext from it, one per scope. Both contexts share the one database: Trax's tables in trax, Shopfront's in shop.

EnsureSchemaCreatedAsync runs once the host is built. It creates the shop schema and any table the model has that the database does not, with its seed rows, and leaves every existing table as it is. That suits a first deployment. It compares tables by name only, so when a later chapter changes a table's columns, the development database has to be recreated, or the context moved to EF migrations.

SDK Reference

DomainDataContext | EnsureSchemaCreatedAsync | Add a domain data context | IFailureClassifier | Architecture guards


Next: 4.8 Run it