Visor.SqlServer 1.2.0

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

Visor

Visor Logo Placeholder

High-performance, Source-Generated ORM for .NET 10+. Treats your Database Stored Procedures as a strictly typed API. Visor is not about generating SQL queries; it's about efficiently consuming Database Endpoints.

NuGet Version NuGet Downloads License: MIT Platform

Visor is designed to solve the "Enterprise Gap" in .NET data access:

  • Dapper is fast but type-unsafe and requires boilerplate.
  • EF Core is convenient but heavy and slow for bulk operations.
  • Visor uses Source Generators to write zero-allocation ADO.NET code for you at compile time. Visor automates TVP boilerplate that you usually write manually.

🧠 Philosophy: Database as an API

Visor was not born solely for performance. It is an architectural statement: The Database should be treated as a strict external API.

  1. Stored Procedures are Endpoints. Just like REST controllers, your Stored Procedures are the entry points.
  2. Strict Contracts. You don't "query" the database; you consume it. The [Endpoint] attribute binds your code to the DB schema at compile time.
  3. No SQL in C#. Visor is not a query builder. It is a high-performance execution engine for your data contracts.

πŸš€ Benchmarks: The "10k Insert" Challenge

We compared inserting 10,000 records into MS SQL Server using a Transactional Stored Procedure with Table-Valued Parameters (TVP).

Method Operation Time (Mean) Memory Allocated GC Gen0/1/2
Visor (TVP) Streaming 51.82 ms 1.07 MB 0 / 0 / 0
EF Core 10 Bulk Insert 517.73 ms 65.04 MB 8 / 3 / 1
Dapper Loop Insert 43,069.73 ms 15.34 MB 1 / 0 / 0

Why is Visor 10x faster than EF and 800x faster than loops?

  • Zero Allocation Streaming: Visor maps List<T> directly to IEnumerable<SqlDataRecord> (MSSQL) or Arrays (Postgres) using yield return. No intermediate DataTable or memory copying.
  • No Runtime Reflection: All mapping code is generated at compile-time.
  • Strict Mapping: If your DB schema changes, Visor fails fast with clear exceptions, not silent data corruption.

⚑ Quick Install

Install the provider for your database and the generator package:

# 1. Add the Source Generators (The Engine)
dotnet add package Visor.Generators

# 2. Add your Database Provider
dotnet add package Visor.SqlServer
# OR
dotnet add package Visor.PostgreSql

πŸ“¦ Ecosystem

Visor is modular. You typically only need to install a Provider and the Generators.

Package Description Version
Visor.SqlServer Main Provider. Includes TVP streaming & async logic. NuGet
Visor.PostgreSql Postgres Provider. Supports Arrays & Composite Types. NuGet
Visor.Generators Required. Roslyn Source Generators (Compile-time magic). NuGet
Visor.Abstractions Attributes & Interfaces only. Keep your Domain clean. NuGet
Visor.Core Shared runtime infrastructure (Internal). NuGet

⚑ Quick Start (MSSQL)

1. Define your Data Contract

Describe your Stored Procedure as a C# interface.

using Visor.Abstractions;

[Visor(VisorProvider.SqlServer)]
public interface IUserRepository
{
    // 1. Simple Execute (Scalar)
    [Endpoint("sp_GetUserCount")]
    Task<int> GetCountAsync();

    // 2. Read Data (DTO Mapping)
    [Endpoint("sp_GetUserById")]
    Task<UserDto> GetUserAsync(int id);

    // 3. High-Performance Bulk Insert (TVP)
    [Endpoint("sp_ImportUsers")]
    Task ImportUsersAsync(List<UserItemDto> users);
}

2. Define your DTOs

Use [VisorColumn] with the universal VisorDbType enum. It automatically maps to SqlDbType.Int in MSSQL context.

[VisorTable("dbo.UserListType")] // Matches SQL User-Defined Type
public class UserItemDto
{
    [VisorColumn(0, VisorDbType.Int32)]
    public int Id { get; set; }

    [VisorColumn(1, VisorDbType.String, Size = 100)]
    public string Name { get; set; }
}

3. Register & Use

Visor generates the implementation class UserRepository automatically.

// In Program.cs
services.AddScoped<IVisorConnectionFactory>(sp => 
    new SqlServerConnectionFactory("Server=..."));
services.AddScoped<IUserRepository, UserRepository>();

// In your Service
public class MyService(IUserRepository repo)
{
    public async Task SyncUsers(List<UserItemDto> users)
    {
        // This executes with Zero Allocation!
        await repo.ImportUsersAsync(users);
    }
}

🐘 Quick Start (PostgreSQL)

Visor fully supports PostgreSQL via Npgsql. It maps List<T> parameters to PostgreSQL Arrays/Composite Types automatically.

1. Define Interface

Specify the provider in the attribute.

[Visor(VisorProvider.PostgreSql)] // <--- Switch to Postgres
public interface IPgUserRepo
{
    [Endpoint("sp_import_users")]
    Task ImportUsersAsync(List<PgUserItem> users);
}

2. Configure Bootstrapper (Important!)

PostgreSQL requires composite types to be registered at startup. Visor generates a helper method for this.

// In Program.cs
var dataSourceBuilder = new NpgsqlDataSourceBuilder("Host=...");

// This method is AUTO-GENERATED by Visor! 
// It registers all types marked with [VisorTable].
dataSourceBuilder.UseVisor(); 

var dataSource = dataSourceBuilder.Build();

services.AddScoped<IVisorConnectionFactory>(sp => 
    new PostgreSqlConnectionFactory(dataSource));

3. Define DTO

Use [VisorColumn] with Name property to map C# PascalCase to Postgres snake_case. Types are inferred automatically or mapped from VisorDbType.

[VisorTable("user_list_type")]
public class PgUserItem
{
    // Use 'Name' to map to lowercase Postgres columns
    [VisorColumn(0, Name = "id")] 
    public int Id { get; set; }

    // VisorDbType.String maps to 'text' in Postgres
    [VisorColumn(1, VisorDbType.String, Name = "user_name")]
    public string UserName { get; set; }
}

πŸŽ›οΈ Advanced: Output Parameters & Return Values

Real-world Enterprise Stored Procedures often return more than just data β€” they return pagination metadata, status codes, and calculated values via OUTPUT parameters.

Visor handles this elegantly using the Response Wrapper pattern.

1. Define a Wrapper Class

Create a class that describes everything the procedure returns. Use [VisorResultSet] for the data list, and [VisorOutput] for parameters.

public class SearchResult
{
    // The main data (SELECT * FROM ...)
    [VisorResultSet]
    public List<UserDto> Users { get; set; }

    // Maps to @TotalCount OUTPUT parameter
    [VisorOutput("TotalCount")]
    public int TotalCount { get; set; }

    // Maps to the RETURN statement (e.g., RETURN 0)
    [VisorReturnValue]
    public int ReturnCode { get; set; }
}

2. Update Interface

Return the wrapper class instead of a List.

[Visor(VisorProvider.SqlServer)]
public interface IAdvancedRepo
{
    [Endpoint("sp_SearchUsers")]
    Task<SearchResult> SearchAsync(string filter);
}

3. Usage

Visor automatically handles the ADO.NET complexity: executing the reader, mapping the list, closing the reader, and then populating the output parameters.

var result = await repo.SearchAsync("Alice");

Console.WriteLine($"Found {result.Users.Count} out of {result.TotalCount}.");
if (result.ReturnCode != 0) { /* Handle error */ }

πŸ›‘οΈ Transaction Support

Visor supports explicit transactions via the VisorDbLease pattern (Unit of Work).

public async Task CreateOrderFlow(OrderDto order)
{
    // Start a transaction scope (scoped per request)
    await _factory.BeginTransactionAsync();

    try 
    {
        // These repositories will automatically share the active transaction
        await _orders.CreateAsync(order);
        await _inventory.DecreaseStockAsync(order.ProductId, order.Quantity);

        await _factory.CommitTransactionAsync();
    }
    catch
    {
        await _factory.RollbackTransactionAsync();
        throw;
    }
}

🧠 The "White Box" Approach

Most ORMs are "Black Boxes" β€” they do magic at runtime that you can't see or debug easily. Visor is a "White Box".

  • It generates readable C# code in your obj/Generated folder.
  • You can step through the generated code with a debugger.
  • You can see exactly how SqlDataReader or NpgsqlDataReader is being read.
  • Strict by Default: If a column is missing in the result set, Visor throws a VisorMappingException immediately, preventing "silent zero" bugs in production.

πŸ—ΊοΈ Roadmap

We are actively bridging the gap between raw speed and developer experience.

  • Core Features: MSSQL & PostgreSQL Support, TVP Streaming, Transactions.
  • Complex Mapping: Output Parameters, Return Values, Composite Types.
  • NuGet Packaging: automated CI/CD flow.
  • Railway Oriented Programming: Native support for Result<T> and functional flows.
  • Resiliency: Retry policies & Circuit Breaker integration.
  • Command Config: Per-command Timeouts & Behaviors.
  • Observability: Advanced OpenTelemetry Tracing, Metrics & Logging.
  • More Providers: Oracle, MySQL, CosmosDB, MongoDB.
  • Configuration: Json-based Database configuration support.
  • CLI Tool: Database-First scaffolding. (See README-CLI.md)

License

Distributed under the MIT License. See LICENSE for more information.

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
1.2.0 666 12/1/2025
1.1.2 180 11/25/2025
1.1.1 175 11/24/2025
1.1.0 180 11/24/2025