DcsvIo.D2.Location.EntityFrameworkCore
0.1.1
dotnet add package DcsvIo.D2.Location.EntityFrameworkCore --version 0.1.1
NuGet\Install-Package DcsvIo.D2.Location.EntityFrameworkCore -Version 0.1.1
<PackageReference Include="DcsvIo.D2.Location.EntityFrameworkCore" Version="0.1.1" />
<PackageVersion Include="DcsvIo.D2.Location.EntityFrameworkCore" Version="0.1.1" />
<PackageReference Include="DcsvIo.D2.Location.EntityFrameworkCore" />
paket add DcsvIo.D2.Location.EntityFrameworkCore --version 0.1.1
#r "nuget: DcsvIo.D2.Location.EntityFrameworkCore, 0.1.1"
#:package DcsvIo.D2.Location.EntityFrameworkCore@0.1.1
#addin nuget:?package=DcsvIo.D2.Location.EntityFrameworkCore&version=0.1.1
#tool nuget:?package=DcsvIo.D2.Location.EntityFrameworkCore&version=0.1.1
DcsvIo.D2.Location.EntityFrameworkCore
Audience: backend .NET service engineers mapping
DcsvIo.D2.Locationvalue objects into EF Core entity models via infraIEntityTypeConfiguration<T>.
Per-VO complex-type and value-converter mapping helpers for the DcsvIo.D2.Location value
objects (StreetAddress, AdminLocation, Coordinates). The helpers are called from the
host's IEntityTypeConfiguration<T> implementation — the domain aggregate holds plain
VO-typed properties and carries zero EF references.
Each helper, in one call:
- Wires member value converters where needed (
CountryCode,SubdivisionCode) - Applies
HasMaxLengthfromFieldConstraints.*caps (plus the encoder-intrinsic geohash / plus-code caps) - Writes the per-field anonymize defaults via the fluent
.Anonymize*API (DcsvIo.D2.DataGovernance.EntityFrameworkCore)
Ships no DbContext, no migrations, and no DI engine. The host owns all of those.
Install
dotnet add package DcsvIo.D2.Location.EntityFrameworkCore
Domain purity
Host aggregates hold VO-typed properties as plain CLR properties:
// Host domain aggregate — ZERO EF references.
public sealed class Sighting
{
public required StreetAddress Where { get; init; }
public AdminLocation? Admin { get; init; }
public Coordinates? Coords { get; init; }
}
All EF mapping (converters, lengths, anonymize annotations) lives in the host's infra
IEntityTypeConfiguration<T> class, which calls the toolkit helpers:
// Host infra layer — SightingConfiguration.cs (NOT in the toolkit; illustrative).
internal sealed class SightingConfiguration : IEntityTypeConfiguration<Sighting>
{
public void Configure(EntityTypeBuilder<Sighting> b)
{
b.ComplexProperty(s => s.Where, cp => cp.MapStreetAddress());
b.ComplexProperty(s => s.Admin, cp => cp.MapAdminLocation());
b.ComplexProperty(s => s.Coords, cp => cp.MapCoordinates());
}
}
Multi-field VO helpers (complex types)
Called from inside a b.ComplexProperty(…, cp => …) callback. No selector arg — the host
already opened the ComplexPropertyBuilder<TComplex>; the helper decorates cp's members.
| Helper | VO | Anonymize defaults |
|---|---|---|
cp.MapStreetAddress() |
StreetAddress (Line1–5/HashId) |
Line1 → "[deleted]" (constant); Line2–5 → SetNull; HashId → cleared sentinel |
cp.MapAdminLocation() |
AdminLocation (City/PostalCode/Subdivision/Country/HashId) |
City/PostalCode/Subdivision → SetNull; Country KEPT (coarse, no annotation); HashId → cleared sentinel |
cp.MapCoordinates() |
Coordinates (Latitude/Longitude/Geohash/PlusCode/AccuracyMeters/HashId) |
Latitude/Longitude → "0" (constant, coerced to 0.0); Geohash/PlusCode → SetEmpty; AccuracyMeters → SetNull; HashId → cleared sentinel |
Value converters encapsulated inside the helpers (the host never hand-wires them):
AdminLocation.SubdivisionIso31662Code→SubdivisionCode ↔ .Value string+HasMaxLength(8)(an empty stored value reads back asnull, neverSubdivisionCode(""))AdminLocation.CountryIso31661Alpha2Code→CountryCode enum ↔ alpha-2 name string
Required-numeric anonymize coercion. Coordinates.Latitude / Longitude are required
non-nullable double columns, so the V7 nullable guard forbids SetNull. They take a
constant "0" string; the anonymization engine coerces it to 0.0 through the column's
type mapping at erasure time. The required geohash / plus-code strings clear to empty
(SetEmpty); only the nullable AccuracyMeters clears to null.
Same-VO-type-twice (e.g. home + work AdminLocation) works natively: the host calls
MapAdminLocation() twice via two distinct host-property selectors. EF Core 10 prefixes
columns by the owning-property path automatically (HomeLocation_City vs
WorkLocation_City). The helpers never call HasColumnName, which preserves this default
uniquification.
Per-VO anonymize-default table
| VO | Field | Default | Note |
|---|---|---|---|
| StreetAddress | Line1 | "[deleted]" |
Non-nullable — constant required |
| StreetAddress | Line2–Line5 | SetNull | Nullable |
| StreetAddress | HashId | cleared sentinel ("v1." + 64×'0') |
|
| AdminLocation | City/PostalCode/SubdivisionIso31662Code | SetNull | Nullable |
| AdminLocation | CountryIso31661Alpha2Code | KEPT | Coarse-grained, not anonymized |
| AdminLocation | HashId | cleared sentinel | |
| Coordinates | Latitude/Longitude | "0" (constant) |
Non-nullable numeric — coerced to 0.0 |
| Coordinates | Geohash/PlusCode | SetEmpty | Non-nullable string |
| Coordinates | AccuracyMeters | SetNull | Nullable |
| Coordinates | HashId | cleared sentinel |
Tombstone values are non-i18n literals — deliberately stable across locales.
Host responsibilities
- Register the anonymization engine:
services.AddD2DataGovernance(…). - Apply anonymization conventions: call
ApplyAnonymizationConventions()onModelConfigurationBuilderinConfigureConventions. - Implement
IUserOwned+IAnonymizationTrackableon entities that carry anonymizable location data.
EF Core 10 complex-member-index limitation
For the EF Core 10 limitation on indexing ComplexProperty member columns (e.g.
AdminLocation.City) and the CreateD2Index workaround, see
DcsvIo.D2.EntityFrameworkCore.
Telemetry
No telemetry surface — mapping helpers are pure model-build-time calls with no runtime span or metric emission.
Edge cases / gotchas
SetNullon required numeric columns blocked —Coordinates.Latitude/Longitudeare non-nullabledoublecolumns. The V7 startup guard inDcsvIo.D2.DataGovernanceblocksSetNullon non-nullable columns. Both fields take a constant"0"anonymization rule; the engine coerces"0"to0.0through the column's type mapping at erasure time.- Country field intentionally kept —
AdminLocation.CountryIso31661Alpha2Codecarries no anonymization annotation. Country is coarse-grained and deliberately retained for analytics post-erasure. - Same-VO-type-twice (e.g. home + work
AdminLocation) works natively. EF Core 10 prefixes columns by the owning-property path automatically. The helpers never callHasColumnName.
Configuration
No configuration — the helpers carry no tunable behavior. All caps come from the shared FieldConstraints codegen catalog.
Dependencies
DcsvIo.D2.Location(location/core/) — theStreetAddress/AdminLocation/CoordinatesVO types being mappedDcsvIo.D2.Validation.Abstractions—FieldConstraints.*length capsDcsvIo.D2.DataGovernance.EntityFrameworkCore— the fluent.Anonymize*APIMicrosoft.EntityFrameworkCore.Relational—ComplexPropertyBuilder<T>,ComplexTypePropertyBuilder<T>,HasMaxLength,HasConversion
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- DcsvIo.D2.DataGovernance.EntityFrameworkCore (>= 0.1.1)
- DcsvIo.D2.Location (>= 0.1.1)
- DcsvIo.D2.Validation.Abstractions (>= 0.1.1)
- dotenv.net (>= 4.0.2)
- JetBrains.Annotations (>= 2025.2.4)
- Microsoft.EntityFrameworkCore (>= 10.0.7)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.7)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Caching.Memory (>= 10.0.7)
- Microsoft.Extensions.Configuration (>= 10.0.7)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.7)
- Microsoft.Extensions.DependencyInjection (>= 10.0.7)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Logging (>= 10.0.7)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.7)
- Microsoft.Extensions.Options (>= 10.0.7)
- Microsoft.IdentityModel.Tokens (>= 8.16.0)
- NodaTime (>= 3.2.2)
- Npgsql (>= 10.0.2)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 10.0.1)
- Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime (>= 10.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.