DCoding.Data.DVault.Analyzers 10.100.0

dotnet add package DCoding.Data.DVault.Analyzers --version 10.100.0
                    
NuGet\Install-Package DCoding.Data.DVault.Analyzers -Version 10.100.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DCoding.Data.DVault.Analyzers" Version="10.100.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DCoding.Data.DVault.Analyzers" Version="10.100.0" />
                    
Directory.Packages.props
<PackageReference Include="DCoding.Data.DVault.Analyzers">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DCoding.Data.DVault.Analyzers --version 10.100.0
                    
#r "nuget: DCoding.Data.DVault.Analyzers, 10.100.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DCoding.Data.DVault.Analyzers@10.100.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DCoding.Data.DVault.Analyzers&version=10.100.0
                    
Install as a Cake Addin
#tool nuget:?package=DCoding.Data.DVault.Analyzers&version=10.100.0
                    
Install as a Cake Tool

DCoding.Data.DVault.Analyzers

Roslyn analyzers and source generators for DVault compile-time metadata declarations. The v1 package reports:

  • DMV1901 for unsupported BusinessKey(...), Payload(...), or DrivingKey(...) selector shapes.
  • DMV1902 for duplicate logical member declarations inside the same applicable Code-First builder lambda scope.
  • DMV1910 for exposing DVault generated shared-type tables as DbSet<Dictionary<string, object>> members on a DbContext.
  • DMV1911 for direct EF write calls against DVault generated shared-type DbSet<Dictionary<string, object>> sets.
  • DMV1912 for source-visible caller-owned DVault model-shape variation whose visible model-cache key omits the varying discriminator.
  • DMV1913 for source-visible UseModel(...) compiled-model selection on variable-shape DVault contexts.
  • DMV1914 for direct AddDbContextPool<TContext>(...) registration of variable-shape DVault contexts.
  • DMV1950 through DMV1955 for malformed generated mapping declarations, missing generated row bindings, invalid source members, duplicate binding order or names, and duplicate link produced participant names.
  • DMV1960 through DMV1969 for typed read-model generator metadata-source, fingerprint, unsupported-shape, deterministic-name, nullability-fallback, and skipped-helper outcomes.

The package also provides bounded code fixes for DMV1901 anonymous-object direct-member expansion and DMV1902 later-duplicate removal. Its mapping source generator emits registry-backed typed row mappers from the public DCoding.Data.DVault compile-time mapping attributes; generated save helpers still require callers to supply load timestamps and record sources through the existing explicit save flow. Its typed read-model source generator is a separate opt-in support-bundle-driven surface for satellite latest/current/as-of helpers, PIT as-of helpers, and bounded bridge traversal helpers.

The lifecycle diagnostics DMV1912 through DMV1914 are high-confidence EF Core misuse diagnostics for direct source-visible evidence only. They align with the root README section "Isolate EF model cache entries" and with docs/architecture/dvault-ef-compiled-compatibility.md; they do not add runtime guards, runtime behavior changes, compiled-model generation, provider-specific lifecycle guarantees, cross-assembly inference, or whole-application inference.

Installation

Install the analyzer package in projects that declare DVault Code-First metadata, compile-time generated row mappings, or support-bundle-driven typed satellite, PIT, and bridge read helpers through normal Roslyn analyzer package conventions. Use the analyzer version from the same selected coordinated DVault package line as the runtime and provider packages: 8.100.0 for net8.0 and EF Core 8, or 10.100.0 for net10.0 and EF Core 10. Build projects that reference DCoding.Data.DVault.Analyzers with either a .NET 8 SDK or .NET 10 SDK host. The package ships one netstandard2.0 analyzer asset under analyzers/dotnet/cs/ for both coordinated package lines. Do not use a consumer-facing 0.100.0 package version from the v0.100.0 documentation release label and do not mix analyzer and runtime/provider package lines. This documentation baseline does not by itself confirm package publication.

For net8.0 projects on EF Core 8, use the 8.100.0 package line:

<ItemGroup>
  <PackageReference Include="DCoding.Data.DVault.Analyzers" Version="8.100.0" PrivateAssets="all" />
</ItemGroup>

For net10.0 projects on EF Core 10, use the 10.100.0 package line:

<ItemGroup>
  <PackageReference Include="DCoding.Data.DVault.Analyzers" Version="10.100.0" PrivateAssets="all" />
</ItemGroup>

PrivateAssets="all" keeps the analyzer local to the project that owns the declarations. The package supplies analyzer assets and does not require a runtime reference from application code.

Code-First Analyzer Scope

The analyzer slice inspects the first direct lambda selector passed to BusinessKey(...), Payload(...), and DrivingKey(...). It expects one direct readable scalar member on the configured entity type, such as hub.BusinessKey(customer => customer.CustomerId) or satellite.Payload(customer => customer.EmailAddress).

Composite business keys, payloads, and driving keys should use repeated single-member calls in their canonical order. When an anonymous-object selector contains only direct readable scalar member accesses, the DMV1901 code fix can expand it into repeated same-verb single-member calls in source order. The DMV1901 code fix is intentionally not offered for selector variables, indirect selectors, computed selectors, nested selectors, method calls, collection-valued selectors, or mixed anonymous-object selectors that are not mechanically expandable.

The DMV1902 code fix removes the later duplicate BusinessKey(...), Payload(...), or DrivingKey(...) declaration and leaves the first declaration authoritative within the same fluent scope.

EF Core Misuse Analyzer Scope

The EF Core misuse analyzer keeps the generated DVault table boundary explicit. Generated hub, link, and satellite tables are EF shared-type entities; applications should not publish them as DbSet<Dictionary<string, object>> members on their DbContext. Use IDataVaultSaveService for writes and keep generated table access behind explicit context.Set<Dictionary<string, object>>(producedName) query shapes.

DMV1910 reports exposed DbContext properties or fields whose type is DbSet<Dictionary<string, object>> when the member source visibly resolves a DVault generated table name through Set<Dictionary<string, object>>(producedName). DMV1911 reports direct mutating calls such as Add(...), AddRange(...), Update(...), Remove(...), or Attach(...) on source-visible generated shared-type sets. The rule intentionally does not report arbitrary non-DVault dictionary shared-type tables, documented read-only query shapes over context.Set<Dictionary<string, object>>(producedName), including AsNoTracking() and compiled-query projections, or a local source scope that visibly opts into UseDataVaultSaveChangesMetadataInterceptor(...).

The analyzer does not attempt whole-application DI inference and does not treat UseDataVaultSaveChangesMetadataInterceptor(...) as a replacement for the explicit save boundary. That interceptor remains an opt-in metadata filler for tracked generated rows; ordinary hub, link, and satellite writes should flow through IDataVaultSaveService. The runtime UseDataVaultSaveChangesGuardInterceptor(...) is a separate opt-in blocking or warning guard for applications that want SaveChanges-time enforcement; it is not enabled by AddDVault() and does not broaden the analyzer into arbitrary dataflow or provider-specific SQL analysis.

DMV1912 reports when direct ApplyDataVaultMetadata(...) model projection visibly varies by caller-owned context state or branches and the directly visible IModelCacheKeyFactory path omits that same discriminator. Registry-backed UseDataVaultMetadata(), UseDataVaultMetadata(DataVaultMetadataModel), UseDataVaultMetadata(DataVaultMetadataRegistry), and UseDataVaultMetadata(DataVaultModelImportResult) are non-diagnostic because DVault carries the metadata-source kind and deterministic metadata fingerprint into EF model-cache isolation.

DMV1913 reports direct UseModel(...) compiled-model selection when the same source visibly applies that runtime model to a DVault context whose realized model shape can vary. Fixed-shape contexts and the documented design-model-to-runtime-model lane remain non-diagnostic because they select one realized DVault model shape. Read-only EF compiled queries over generated shared-type tables remain non-diagnostic because they compile a stable query expression rather than selecting an EF compiled model for a context.

DMV1914 reports direct AddDbContextPool<TContext>(...) registration when the target DVault context visibly has model-shape variation. Options-only pooled contexts with one fixed metadata source, provider configuration, naming, schema, and profile remain non-diagnostic. Pooled factories, helper-expanded registrations, and cross-assembly inference stay outside this analyzer slice.

The lifecycle diagnostics are intentionally limited to direct syntax and semantic facts in the analyzed source: visible instance members read in OnModelCreating(...), direct branches around DVault model projection, direct ReplaceService<IModelCacheKeyFactory, ...>() paths, directly visible returned cache-key shapes, and direct UseModel(...) or AddDbContextPool<TContext>(...) registrations. When the source does not make both the variable model shape and unsafe lifecycle path visible, the analyzer skips instead of guessing.

Generated Mapper Scope

The source generator recognizes mapping declarations from DCoding.Data.DVault runtime attributes on one source type:

  • DataVaultHubMappingAttribute plus ordered DataVaultBusinessKeyBindingAttribute values.
  • DataVaultLinkMappingAttribute plus ordered DataVaultLinkParticipantBindingAttribute values whose produced participant names are unique by StringComparer.Ordinal; ordinary links use hub names, while repeated same-hub links use explicit role-bearing names such as SourceCustomer and MatchedCustomer.
  • DataVaultHubSatelliteMappingAttribute plus parent hash-key, hash-diff, ordered payload, and optional ordered driving-key bindings.

Generated code implements the existing IDataVaultHubMapper<TSource>, IDataVaultLinkMapper<TSource>, or IDataVaultSatelliteMapper<TSource> contracts and constructs DataVaultRegistry*SaveOperation values. It does not execute EF models, register mappings at runtime, derive hash keys or hash diffs, or hide the caller-supplied loadTimestamp and recordSource boundary.

Typed Read-Model Generator Scope

The typed read-model source generator emits satellite latest/current/as-of helpers, bounded PIT as-of helpers, and bounded bridge traversal helpers from one authoritative dvault.support-bundle.v1 JSON additional file. Enable it explicitly in the owning project with DVaultGenerateTypedReadModels=true; this keeps application and test projects that contain multiple sample metadata models from accidentally generating colliding public helpers. The support bundle must be produced from runtime diagnostics after Code-First, metadata-first, or model-first declarations have been projected into EF/DVault metadata. Generated satellite helpers use its diagnostics.explain metadata source kind, fingerprint, produced entity/property names, parent references, property roles, provider logical/value metadata, ordinals, CLR type names, and EF nullability. Generated PIT helpers additionally require request-bound diagnostics.readShape.pit facts for PIT identity, parent reference, referenced satellites, snapshot-reference columns, and canonical driving-key columns. Generated bridge helpers require request-bound diagnostics.readShape.bridge facts for bridge kind, endpoint vocabulary, endpoint columns, selected filter endpoint, deterministic ordering, and hierarchy depth projection when applicable. Source-visible Code-First callbacks, literal metadata-first DataVaultMetadataModel declarations, and raw dvault.model.v1 JSON additional files are not parsed directly by this generator because they have not yet passed through the shared EF/DVault projection descriptor.

Generated rows are emitted under {RootNamespace}.DVault.GeneratedReadModels when MSBuild supplies RootNamespace, otherwise under DVault.GeneratedReadModels. For each supported satellite, the generator emits {SatelliteProducedName}ReadModel and {SatelliteProducedName}ReadExtensions with Read...CurrentAsync, Read...LatestAsync, and Read...AsOfAsync methods over IDataVaultReadService. The helpers construct stable DataVaultSatelliteMetadata and DataVaultLatestSatelliteReadRequest values and project through the existing DataVaultSatelliteProjectionRow exact-name accessors.

For each supported PIT, the generator emits {PitProducedName}ReadModel and {PitProducedName}ReadExtensions with Read...AsOfAsync over IDataVaultReadService. The helper constructs stable DataVaultPitMetadata and DataVaultPitAsOfReadRequest values, delegates to ReadPitRowsAsync, and projects PIT-table columns only: ParentHashKey, LoadTimestamp, canonical PIT driving keys when the read shape proves one shared multi-active driving-key family, and nullable snapshot-reference timestamps for each included PIT segment.

For each supported bridge, the generator emits {BridgeProducedName}ReadModel and {BridgeProducedName}ReadExtensions over IDataVaultReadService. Many-to-many bridges emit Read...FromAsync and Read...ToAsync helpers. Hierarchy bridges emit Read...AncestorAsync and Read...DescendantAsync helpers that require an explicit int maximumDepth; the generator does not emit an unbounded hierarchy traversal overload. Bridge helpers construct stable DataVaultBridgeMetadata and DataVaultBridgeReadRequest values, delegate through the runtime read boundary, and project bridge-row endpoint columns plus TraversalDepth for hierarchy rows.

The v1 generator supports hub-parent, link-parent, and deterministic multi-active satellites whose driving keys and payload values are strings after projection into the support-bundle explain descriptor. Payload nullability follows the projected CLR/EF nullability facts; when a payload descriptor omits nullability, the generated property is nullable and DMV1966 is reported. PIT helper emission is limited to hub-parent ordinary PITs, hub-parent PITs whose multi-active satellites share one canonical driving-key family, and bounded link-parent PITs with unique non-multi-active satellites on one declared link parent. Bridge helper emission is limited to maintained many-to-many From/To traversal and maintained hierarchy Ancestor/Descendant traversal with required maximumDepth. Generation stops or skips helpers with DMV196x diagnostics for missing or ambiguous support-bundle metadata sources, stale configured fingerprints, unsupported non-string members, deterministic name collisions, helper requests that would require dynamic query construction or provider-specific SQL, unbounded traversal, and shapes outside the v1 generated-helper contract.

The support-bundle-driven satellite, PIT, and bridge helper contract is documented in DVault V1 Typed PIT And Bridge Helper Contract.

Typed Read-Model Diagnostics

Code Outcome
DMV1960 Missing, invalid, incompatible-version, non-authoritative, or ambiguous dvault.support-bundle.v1 metadata source, including raw or residual dvault.model.v1 additional files outside the projected support-bundle contract.
DMV1961 Configured DVaultTypedReadModelMetadataSourceFingerprint does not match the resolved support-bundle metadata-source fingerprint.
DMV1962 Satellite shape cannot be generated, including non-string driving-key or payload members and reserved generated projection-name collisions.
DMV1963 PIT metadata or request-bound PIT read-shape evidence is incomplete or outside the bounded generated-helper baseline.
DMV1964 Bridge metadata or request-bound bridge read-shape evidence is incomplete or outside the bounded generated-helper baseline.
DMV1965 Deterministic generated type, method, property, or helper name collision.
DMV1966 Payload nullability cannot be proven from the support-bundle descriptor, so the generated payload property falls back to nullable.
DMV1967 The shape would require dynamic runtime query construction, provider SQL, runtime projection selection, or unbounded traversal.
DMV1968 Reserved for future model-first-specific typed helper outcomes; current raw or residual model-first additional files are source-boundary failures reported as DMV1960. Complete model-first support bundles with request-bound ReadShape evidence can still emit supported helpers.
DMV1969 A valid runtime metadata shape is skipped because it is outside the v1 generated-helper boundary.

Suppression

Suppress DMV diagnostics only where the consuming project intentionally accepts a pattern outside this analyzer slice. Use standard C# and Roslyn analyzer suppression mechanisms.

For a narrow local exception, use a pragma around the intentional declaration:

#pragma warning disable DMV1901
satellite.Payload(emailSelector);
#pragma warning restore DMV1901

For a project or path-level policy, configure analyzer severities in .editorconfig:

dotnet_diagnostic.DMV1901.severity = none
dotnet_diagnostic.DMV1902.severity = none
dotnet_diagnostic.DMV1910.severity = none
dotnet_diagnostic.DMV1911.severity = none
dotnet_diagnostic.DMV1912.severity = none
dotnet_diagnostic.DMV1913.severity = none
dotnet_diagnostic.DMV1914.severity = none

For MSBuild-level suppression, append the diagnostic ids to NoWarn:

<PropertyGroup>
  <NoWarn>$(NoWarn);DMV1901;DMV1902;DMV1910;DMV1911;DMV1912;DMV1913;DMV1914</NoWarn>
</PropertyGroup>
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.100.0 146 7/2/2026
10.51.0 124 7/1/2026
10.50.0 124 6/29/2026
10.49.0 121 6/28/2026
10.48.0 134 6/26/2026
10.46.0 130 6/25/2026
10.45.0 127 6/23/2026
10.44.0 113 6/22/2026
10.43.0 121 6/21/2026
10.42.0 116 6/21/2026
8.100.0 110 7/2/2026
8.51.0 106 7/1/2026
8.50.0 122 6/29/2026
8.49.0 119 6/28/2026
8.48.0 128 6/26/2026
8.46.0 126 6/25/2026
8.45.0 116 6/23/2026
8.44.0 109 6/22/2026
8.43.0 112 6/21/2026
8.42.0 126 6/21/2026
Loading failed

DVault v0.100.0 breaking release: publish package versions 8.100.0 for net8.0/EF Core 8 and 10.100.0 for net10.0/EF Core 10; generated hash-key and participant-reference columns now default to binary physical storage; existing HexString schemas should stay on the previous package line or opt into the HexString compatibility profile until migration is reviewed.