BB84.EntityFrameworkCore.Repositories.SqlServer 5.0.1020

dotnet add package BB84.EntityFrameworkCore.Repositories.SqlServer --version 5.0.1020
                    
NuGet\Install-Package BB84.EntityFrameworkCore.Repositories.SqlServer -Version 5.0.1020
                    
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="BB84.EntityFrameworkCore.Repositories.SqlServer" Version="5.0.1020" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BB84.EntityFrameworkCore.Repositories.SqlServer" Version="5.0.1020" />
                    
Directory.Packages.props
<PackageReference Include="BB84.EntityFrameworkCore.Repositories.SqlServer" />
                    
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 BB84.EntityFrameworkCore.Repositories.SqlServer --version 5.0.1020
                    
#r "nuget: BB84.EntityFrameworkCore.Repositories.SqlServer, 5.0.1020"
                    
#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 BB84.EntityFrameworkCore.Repositories.SqlServer@5.0.1020
                    
#: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=BB84.EntityFrameworkCore.Repositories.SqlServer&version=5.0.1020
                    
Install as a Cake Addin
#tool nuget:?package=BB84.EntityFrameworkCore.Repositories.SqlServer&version=5.0.1020
                    
Install as a Cake Tool

net100 NuGet

BB84.EntityFrameworkCore.Repositories.SqlServer

This package provides the SQL Server tuning of the entity type configuration base classes, PropertyBuilderExtensions for column types, EntityTypeBuilderExtensions for temporal table support, and DatabaseFacadeExtensions for calling stored procedures and SQL functions.

Moved in 5.0. The configuration base classes now derive from provider-agnostic bases in BB84.EntityFrameworkCore.Repositories, and the interceptors moved there outright. DatabaseFacadeExtensions moved the other way, into this package, because it emits T-SQL. See Package boundaries.

Installation

dotnet add package BB84.EntityFrameworkCore.Repositories.SqlServer

Package boundaries

Each configuration ladder exists twice, under the same type names:

Namespace Applies
BB84.EntityFrameworkCore.Repositories.Configurations Key declaration, column order, concurrency token, audit columns, soft delete filter
BB84.EntityFrameworkCore.Repositories.SqlServer.Configurations The above, plus clustering, NEWID() defaults and sysname audit columns

Pick the namespace, not the type. On SQL Server, keep importing this package's namespace and nothing changes. On any other provider, import the agnostic one and you get everything except the three SQL Server calls.

A file that imports both namespaces — a project mapping a SQL Server context and a second provider's context side by side — hits CS0104 on the ambiguous name. Alias one of them:

using SqlServerConfigurations = BB84.EntityFrameworkCore.Repositories.SqlServer.Configurations;

Configuration base classes

Inherit from these in your IEntityTypeConfiguration<TEntity> implementations and call base.Configure(builder) to apply the standard column order, constraints, concurrency tokens, and indexes. Override before or after the base call to add entity-specific configuration.

Configuration class For entity type What base.Configure applies
IdentityConfiguration<TEntity, TKey> IIdentityEntity<TKey> Non-clustered PK, Id (ValueGeneratedOnAdd), Timestamp as concurrency token
AuditedConfiguration<TEntity, TKey, TCreator, TEditor> IAuditedEntity<TKey, TCreator, TEditor> Above + CreatedBy (required), EditedBy (optional); the <TEntity, TKey> overload maps both as sysname, the <TEntity> overload adds the NEWID() default too
FullAuditedConfiguration<TEntity, TKey, TCreator, TEditor> IFullAuditedEntity<TKey, TCreator, TEditor> Above + CreatedAt (required), EditedAt (optional); same overload behaviour
CompositeConfiguration<TEntity> ICompositeEntity Timestamp as concurrency token
AuditedCompositeConfiguration<TEntity, TCreator, TEditor> IAuditedCompositeEntity<TCreator, TEditor> Above + audit user columns
EnumeratorConfiguration<TEntity, TKey> IEnumeratorEntity<TKey> Non-clustered PK, Name (nvarchar(64), unique index, non-unicode), Description (nvarchar(256)), IsDeleted default false; int overload uses clustered PK

These stop at the byte[] rung on purpose. The token type is a parameter on the agnostic bases in BB84.EntityFrameworkCore.Repositories, but on SQL Server the concurrency token is a rowversion and a rowversion is eight bytes — there is nothing here for another type to map onto. An entity with a different token type belongs on the agnostic configuration bases.

public class ProductConfiguration : IdentityConfiguration<Product>
{
    public override void Configure(EntityTypeBuilder<Product> builder)
    {
        base.Configure(builder);

        builder.ToTable("Products", "catalog");
        builder.Property(p => p.Name).IsRequired().HasMaxLength(200);
        builder.Property(p => p.Price).IsDecimalColumn(10, 2);
    }
}

public class InvoiceConfiguration : FullAuditedConfiguration<Invoice>
{
    public override void Configure(EntityTypeBuilder<Invoice> builder)
    {
        base.Configure(builder); // applies NEWID() default, sysname for audit columns

        builder.ToTable("Invoices", "billing");
        builder.Property(i => i.Number).IsRequired().HasMaxLength(50);
    }
}

public class ProductCategoryConfiguration : EnumeratorConfiguration<ProductCategory>
{
    public override void Configure(EntityTypeBuilder<ProductCategory> builder)
    {
        base.Configure(builder); // clustered int PK, Name unique index, IsDeleted default false
        builder.ToTable("ProductCategories", "catalog");
    }
}

Apply configurations via ApplyConfigurationsFromAssembly in OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
}

PropertyBuilderExtensions

Extension methods that set the SQL Server column type in one call, each in two forms. The generic form extends PropertyBuilder<TProperty> and returns it unchanged, so the property type survives the call and anything typed later in the chain — HasDefaultValue, HasConversion, HasValueGenerator — stays compile-time checked. The non-generic form extends PropertyBuilder and exists for the Property(string) path used by shadow properties. A lambda-based Property call picks the generic form automatically.

builder.Property(e => e.Price)      // PropertyBuilder<decimal>
    .IsDecimalColumn(10, 2)         // PropertyBuilder<decimal> — type kept
    .HasDefaultValue(0m);           // takes decimal, not object
Method SQL Server type Parameters
IsBinaryColumn(length) binary(n) length: 1–8000 (default 8000); binary has no max form
IsDateColumn() date —
IsDateTimeColumn(small) datetime / smalldatetime small: false → datetime
IsDateTime2Column(precision) datetime2(n) precision: 0–7 (default 7)
IsDateTimeOffsetColumn(precision) datetimeoffset(n) precision: 0–7 (default 7)
IsDecimalColumn(precision, scale) decimal(p,s) precision: 1–38 (default 18), scale: 0–precision (default 2)
IsMoneyColumn(small) money / smallmoney small: false → money
IsSysNameColumn() sysname —
IsTimeColumn(precision) time(n) precision: 0–7 (default 7)
IsUniqueIdentifierColumn() uniqueidentifier —
IsVarbinaryColumn(length) varbinary(n) / varbinary(max) length: 0–8000; 0 → varbinary(max) (default 0)
IsXmlColumn() xml —

Methods with a precision or length parameter throw ArgumentOutOfRangeException when the value is outside the valid range.

public class OrderConfiguration : IdentityConfiguration<Order>
{
    public override void Configure(EntityTypeBuilder<Order> builder)
    {
        base.Configure(builder);

        builder.ToTable("Orders", "sales");

        builder.Property(o => o.TotalAmount)
            .IsDecimalColumn(precision: 18, scale: 4);

        builder.Property(o => o.PlacedAt)
            .IsDateTimeOffsetColumn(precision: 3);

        builder.Property(o => o.DueDate)
            .IsDateColumn();

        builder.Property(o => o.Notes)
            .IsXmlColumn();

        builder.Property(o => o.Attachment)
            .IsVarbinaryColumn(); // varbinary(max)
    }
}

EntityTypeBuilderExtensions

ToHistoryTable

One-line setup for SQL Server temporal tables with a separate history schema:

builder.ToHistoryTable(
    tableName: "Orders",          // defaults to entity class name
    tableSchema: "sales",         // defaults to "dbo"
    historyTableName: "Orders",   // defaults to tableName
    historyTableSchema: "history" // defaults to "history"
);

Interceptors

SoftDeletableInterceptor and TimeAuditedInterceptor moved to BB84.EntityFrameworkCore.Repositories in 5.0 — nothing in them was SQL Server specific. Update the using to BB84.EntityFrameworkCore.Repositories.Interceptors; the types and their behavior are unchanged.

DatabaseFacadeExtensions

Extension methods on DatabaseFacade (context.Database) for calling SQL Server stored procedures and functions safely with parameterized SQL. These moved here from BB84.EntityFrameworkCore.Repositories in 5.0, because the SQL they emit — EXECUTE [schema].[name] @p = @p OUTPUT, SELECT [Value] = [schema].[fn](@p) — is T-SQL by construction.

Stored procedures

// Returns rows as IReadOnlyList<T>
IReadOnlyList<ReportRow> rows = context.Database.ExecuteProcedure<ReportRow>(
    schema: "dbo",
    name: "usp_GetReport",
    parameters: [new SqlParameter("@FromDate", fromDate)]);

// Non-generic overload returns rows-affected count
int affected = context.Database.ExecuteProcedure(
    schema: "dbo",
    name: "usp_ArchiveOrders",
    parameters: [new SqlParameter("@CutoffDate", cutoff)]);

// Async variants
await context.Database.ExecuteProcedureAsync<ReportRow>(..., cancellationToken);
await context.Database.ExecuteProcedureAsync(..., cancellationToken);

Output parameters are supported — parameters with Direction = ParameterDirection.Output are emitted as @param = @param OUTPUT in the generated SQL.

Table-valued functions

IReadOnlyList<ProductDto> results = context.Database.ExecuteTableFunction<ProductDto>(
    schema: "dbo",
    name: "fn_GetActiveProducts",
    parameters: [new SqlParameter("@CategoryId", categoryId)]);

await context.Database.ExecuteTableFunctionAsync<ProductDto>(..., cancellationToken);

Scalar-valued functions

decimal? total = context.Database.ExecuteScalarFunction<decimal>(
    schema: "dbo",
    name: "fn_GetOrderTotal",
    parameters: [new SqlParameter("@OrderId", orderId)]);

await context.Database.ExecuteScalarFunctionAsync<decimal>(..., cancellationToken);

All methods sanitize schema/name inputs and use parameterized SQL to prevent injection. The parameter sequence is materialized once on entry, so a lazily generated IEnumerable<DbParameter> is safe to pass.

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

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
5.0.1020 81 10/20/2026
5.0.916 255 9/16/2026
5.0.818 269 8/18/2026
4.5.725 223 7/25/2026
4.4.724 139 7/24/2026
4.4.625 219 6/25/2026
4.3.520 322 5/20/2026
4.3.513 191 5/13/2026
4.3.507 161 5/7/2026
4.3.419 245 4/19/2026
4.3.327 287 3/27/2026
4.2.322 168 3/22/2026
4.1.319 138 3/19/2026
4.1.222 235 2/22/2026
4.1.122 206 1/22/2026
4.0.1026 416 10/26/2025
4.0.916 490 9/16/2025
4.0.817 305 8/17/2025
3.1.617 399 6/17/2025
3.1.518 276 5/18/2025
Loading failed