Skip to content

v6.8.0

Choose a tag to compare

@github-actions github-actions released this 26 Jul 16:15
· 2 commits to master since this release

The three schema changes the generator used to hand back

eqdata could describe a resize, a collection rename and a collection drop; the engine had no operation for any of them, so the generated file emitted a #error and left them to you. Two now run, and the third is one edit away.

migration.For<OrderData>(order => order
    .ResizeField(x => x.Reference)                        // varchar(50) -> varchar(200)
    .RenameCollection("orders", "sale_orders"));

ResizeField takes only the field: the size is the model's, never the caller's, so the operation cannot disagree with the mapping. It is distinct from ConvertField, which changes what kind of thing is stored and rewrites values — this changes only how much room it has, so the store does the work.

Per store, what each can honestly do:

relational all three — SQL Server renames through sp_rename, MySQL restates with MODIFY
Cassandra drops a table; refuses to rename one (no ALTER does it) and has no sized types to resize
MongoDB drops and renames a collection; resizing is a no-op
Cosmos DB deletes a container; refuses to rename one (the name is fixed at creation); resizing is a no-op

Every refusal names what to do instead. The no-ops are deliberate: one migration is written for six stores, so a step that means nothing on one of them must not throw there.

Dropping a collection still stops the build. It deletes everything in the table, and a model diff cannot tell whether that data is finished with — but the #error names the operation, so it is one edit away.

The model no longer has to live in the application

eqdata migrations add AddCustomerTier \
  --project         src/Shop.Data \
  --startup-project src/Shop.Api

The tool runs an application, and only an application can be run: a library produces no runtimeconfig.json, so the assemblies a model depends on cannot be located from one. --project is where the migrations belong and whose namespace they take; --startup-project is what gets run.

Both assemblies are searched for the design-time services and for the snapshot — which matters, because the snapshot is committed beside the model, in exactly the project that is not being run. Pointing at a library alone still fails, but now it names the option to reach for.

MongoDB drift stops being unanswerable

A collection has no schema, and none is claimed: no field is compared on MongoDB or Cosmos DB, because a document either carries a property or it does not, and sampling would describe the documents that came back rather than the collection.

But a collection does carry the indexes the model asked for — and one of them is not about speed:

The mongodb database and the model disagree:

  expiring_docs  (Shop.ExpiringDoc)
    ttl_CreatedAt is not there — the model expects CreatedAt:1

A time-to-live declaration is delivered as an index. Without it nothing expires, and documents that should have been deleted are still being read. That is the one index whose absence changes what the store holds, so it is the one that fails the check.

Every other index changes how fast a query answers, not whether it does — so a missing or differing one is reported without failing the gate, and an index nobody declared is reported and ignored, like a column nobody mapped.

Store What drift compares
PostgreSQL · MySQL · MariaDB · SQL Server every mapped table and column, each type and nullability
Cassandra the same through system_schema, plus the partition key
Cosmos DB the containers and the partition key paths they were created with
MongoDB the collections and their indexes

A shared Cosmos container is checked once

Sharing a container between entity types is the Cosmos idiom, not a mistake. Five types in one container used to describe it five times and report every difference five times, which reads as five problems. It is now one container named after all the types that map to it, so a finding still says which are affected.


Verified against real stores: MongoDB 148, Cassandra 107, PostgreSQL 89, Cosmos DB 56, MySQL 19, core 83, analyzers 13. Every schema change is checked by asking the database afterwards, not by inspecting the SQL. The startup-project split is verified end to end against a library plus application pair. SQL Server runs in CI (its image is amd64 only).

Docs: Generating and drift checking