VapeCache.Extensions.EntityFrameworkCore 1.2.13

There is a newer version of this package available.
See the version list below for details.
dotnet add package VapeCache.Extensions.EntityFrameworkCore --version 1.2.13
                    
NuGet\Install-Package VapeCache.Extensions.EntityFrameworkCore -Version 1.2.13
                    
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="VapeCache.Extensions.EntityFrameworkCore" Version="1.2.13" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="VapeCache.Extensions.EntityFrameworkCore" Version="1.2.13" />
                    
Directory.Packages.props
<PackageReference Include="VapeCache.Extensions.EntityFrameworkCore" />
                    
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 VapeCache.Extensions.EntityFrameworkCore --version 1.2.13
                    
#r "nuget: VapeCache.Extensions.EntityFrameworkCore, 1.2.13"
                    
#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 VapeCache.Extensions.EntityFrameworkCore@1.2.13
                    
#: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=VapeCache.Extensions.EntityFrameworkCore&version=1.2.13
                    
Install as a Cake Addin
#tool nuget:?package=VapeCache.Extensions.EntityFrameworkCore&version=1.2.13
                    
Install as a Cake Tool

VapeCache.Extensions.EntityFrameworkCore

EF Core adapter package for VapeCache second-level cache interception contracts.

What this package provides

  • deterministic EF query cache-key builder contract (IEfCoreQueryCacheKeyBuilder)
  • default SHA-256 query key builder (Sha256EfCoreQueryCacheKeyBuilder)
  • command interceptor hook for query-key generation (VapeCacheEfCoreCommandInterceptor)
  • save-changes invalidation bridge interceptor (VapeCacheEfCoreSaveChangesInterceptor)
  • DI registration and DbContextOptionsBuilder wiring helpers

Install

dotnet add package VapeCache.Extensions.EntityFrameworkCore

Register

builder.Services.AddVapeCacheEntityFrameworkCore(options =>
{
    options.ZonePrefix = "ef";
    options.EnableObserverCallbacks = true;
});

builder.Services.AddDbContext<MyDbContext>((sp, db) =>
{
    db.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
    db.UseVapeCacheEntityFrameworkCore(sp);
});

Profiler Visibility Hook

Register an observer to receive interceptor events and correlate DB + cache activity.

Observer callbacks are disabled by default (EnableObserverCallbacks = false) to keep overhead at zero unless explicitly enabled.

using System.Threading.Channels;

public enum EfProfilerEventType
{
    QueryKeyBuilt,
    QueryExecutionCompleted,
    InvalidationPlanCaptured,
    ZoneInvalidated,
    ZoneInvalidationFailed
}

public sealed record EfProfilerEvent(
    DateTimeOffset TimestampUtc,
    EfProfilerEventType EventType,
    Guid CommandId,
    Guid ContextInstanceId,
    string? ProviderName,
    string? CacheKey,
    double? DurationMs,
    bool? Succeeded,
    string? Zone,
    long? ZoneVersion,
    string? FailureType,
    string? FailureMessage,
    IReadOnlyList<string>? PlannedZones);

public sealed class EfCacheProfilerObserver : IEfCoreSecondLevelCacheObserver
{
    private readonly ChannelWriter<EfProfilerEvent> _writer;

    public EfCacheProfilerObserver(ChannelWriter<EfProfilerEvent> writer)
    {
        _writer = writer;
    }

    public void OnQueryCacheKeyBuilt(in EfCoreQueryCacheKeyBuiltEvent e)
    {
        _writer.TryWrite(new EfProfilerEvent(
            TimestampUtc: DateTimeOffset.UtcNow,
            EventType: EfProfilerEventType.QueryKeyBuilt,
            CommandId: e.CommandId,
            ContextInstanceId: e.ContextInstanceId,
            ProviderName: e.ProviderName,
            CacheKey: e.CacheKey,
            DurationMs: null,
            Succeeded: null,
            Zone: null,
            ZoneVersion: null,
            FailureType: null,
            FailureMessage: null,
            PlannedZones: null));
    }

    public void OnQueryExecutionCompleted(in EfCoreQueryExecutionCompletedEvent e)
    {
        _writer.TryWrite(new EfProfilerEvent(
            TimestampUtc: DateTimeOffset.UtcNow,
            EventType: EfProfilerEventType.QueryExecutionCompleted,
            CommandId: e.CommandId,
            ContextInstanceId: e.ContextInstanceId,
            ProviderName: e.ProviderName,
            CacheKey: e.CacheKey,
            DurationMs: e.DurationMs,
            Succeeded: e.Succeeded,
            Zone: null,
            ZoneVersion: null,
            FailureType: e.FailureType,
            FailureMessage: e.FailureMessage,
            PlannedZones: null));
    }

    public void OnInvalidationPlanCaptured(in EfCoreInvalidationPlanCapturedEvent e)
    {
        _writer.TryWrite(new EfProfilerEvent(
            TimestampUtc: DateTimeOffset.UtcNow,
            EventType: EfProfilerEventType.InvalidationPlanCaptured,
            CommandId: Guid.Empty,
            ContextInstanceId: e.ContextInstanceId,
            ProviderName: null,
            CacheKey: null,
            DurationMs: null,
            Succeeded: null,
            Zone: null,
            ZoneVersion: null,
            FailureType: null,
            FailureMessage: null,
            PlannedZones: e.Zones));
    }

    public void OnZoneInvalidated(in EfCoreZoneInvalidatedEvent e)
    {
        _writer.TryWrite(new EfProfilerEvent(
            TimestampUtc: DateTimeOffset.UtcNow,
            EventType: EfProfilerEventType.ZoneInvalidated,
            CommandId: Guid.Empty,
            ContextInstanceId: e.ContextInstanceId,
            ProviderName: null,
            CacheKey: null,
            DurationMs: null,
            Succeeded: true,
            Zone: e.Zone,
            ZoneVersion: e.Version,
            FailureType: null,
            FailureMessage: null,
            PlannedZones: null));
    }

    public void OnZoneInvalidationFailed(in EfCoreZoneInvalidationFailedEvent e)
    {
        _writer.TryWrite(new EfProfilerEvent(
            TimestampUtc: DateTimeOffset.UtcNow,
            EventType: EfProfilerEventType.ZoneInvalidationFailed,
            CommandId: Guid.Empty,
            ContextInstanceId: e.ContextInstanceId,
            ProviderName: null,
            CacheKey: null,
            DurationMs: null,
            Succeeded: false,
            Zone: e.Zone,
            ZoneVersion: null,
            FailureType: e.FailureType,
            FailureMessage: e.FailureMessage,
            PlannedZones: null));
    }
}

builder.Services.AddSingleton(Channel.CreateUnbounded<EfProfilerEvent>());
builder.Services.AddSingleton(sp => sp.GetRequiredService<Channel<EfProfilerEvent>>().Writer);
builder.Services.AddSingleton(sp => sp.GetRequiredService<Channel<EfProfilerEvent>>().Reader);
builder.Services.AddSingleton<IEfCoreSecondLevelCacheObserver, EfCacheProfilerObserver>();
builder.Services.AddVapeCacheEntityFrameworkCore(options =>
{
    options.EnableObserverCallbacks = true;
});

Your profiler can consume ChannelReader<EfProfilerEvent> and correlate query and cache behavior using:

  • CommandId for query-key + query-execution events
  • ContextInstanceId for SaveChanges/invalidation events

Notes

  • This package is the EF adapter boundary. Core runtime packages remain EF-free.
  • Query-key generation is deterministic and provider-aware.
  • SaveChanges invalidation is zone-based and designed to integrate with existing tag/zone invalidation APIs.
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on VapeCache.Extensions.EntityFrameworkCore:

Package Downloads
VapeCache.Extensions.EntityFrameworkCore.OpenTelemetry

OpenTelemetry metrics and activity hooks for VapeCache EF Core interceptor events. Enables profiler and Aspire-ready observability for query-key generation and cache invalidation flows.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.22 115 4/26/2026
1.2.21 100 4/26/2026
1.2.20 127 4/13/2026
1.2.19 102 4/12/2026
1.2.18 121 3/30/2026
1.2.17 109 3/27/2026
1.2.15 110 3/19/2026
1.2.14 113 3/18/2026
1.2.13 116 3/14/2026
1.2.12 115 3/14/2026

1.2.12 release: introduced first-party EF Core interceptor contract package with deterministic query key builder and SaveChanges invalidation bridge wiring.