0024. A .NET tool package for model validation in CI
- Status: Accepted
- Date: 2026-11-03
Context
Section titled “Context”Issue #20 asks for dotnet tenantguard validate: the model rules run on a compiled app’s
DbContext in CI, with no host, test project or database. 0002
keeps the runtime package to EF Core alone, and the packages list has three packages. A tool
has to load the app’s own EF Core, providers and TenantGuard, at the app’s versions, and
create its context the way the app configures it.
Decision
Section titled “Decision”- A fourth package,
TenantGuard.Tool, a .NET tool with the commanddotnet-tenantguard(dotnet tenantguard). It has no public API. The validate tool reference page is its contract. - It runs in two processes, as
dotnet efdoes. The tool parses the options, then startsdotnet execwith the app’s.deps.jsonand.runtimeconfig.jsonon a payload built for the app’s target (net10.0 or net11.0), shipped inside the tool package. The payload loads in the app’s dependency context, so no EF Core or provider version is the tool’s own. - The payload creates the context with
DbContextActivatorfromMicrosoft.EntityFrameworkCore.Design, which the app references, asdotnet efrequires, instead of reimplementing the factory and host lookup. - The payload reads the context’s TenantGuard options and runs the internal
TenantModelRules.Check(model, options, contextType), the call the EF convention makes, throughInternalsVisibleTo. So the tool’s version has to match the app’sTenantGuard.EntityFrameworkCore, and it checks that first. - The runtime package stays EF Core only. The tool depends on
Microsoft.EntityFrameworkCore.Design(in the payload) and nothing else; options are parsed by hand, without a command-line library.
Consequences
Section titled “Consequences”CI can check a model with one command and no database. The tool must be released at the
same version as the other packages, which it is, since all of them share Version in
Directory.Build.props. An app without Microsoft.EntityFrameworkCore.Design gets a clear
error asking for it. A version mismatch fails rather than running rules that differ from
the app’s. Packages, the architecture tests and the release now cover four packages.