NuVatis.Extensions.EntityFrameworkCore 1.0.4

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

NuVatis

CI NuGet License: MIT

MyBatis-style SQL Mapper for .NET, powered by Roslyn Source Generators.

Overview

NuVatis는 Entity Framework의 성능 오버헤드와 인라인 SQL의 유지보수성 문제를 동시에 해결하는 SQL Mapper 프레임워크다.

  • SQL은 XML 또는 C# Attribute로 별도 관리
  • Roslyn Source Generator가 빌드타임에 매핑 코드를 자동 생성
  • 런타임 리플렉션 제로, Native AOT 호환 (.NET 8)
  • ADO.NET 기반 최소 추상화, 최대 성능
  • .NET 7 / .NET 8 동시 지원 (멀티 타겟)

Packages

Package Description
NuVatis.Core 핵심 런타임 (Session, Executor, Transaction, Mapping, Cache)
NuVatis.Generators Roslyn Source Generator (XML 파싱, 분석, 코드 생성)
NuVatis.PostgreSql PostgreSQL Provider (Npgsql)
NuVatis.MySql MySQL/MariaDB Provider (MySqlConnector)
NuVatis.SqlServer SQL Server Provider (Microsoft.Data.SqlClient)
NuVatis.Sqlite SQLite Provider (Microsoft.Data.Sqlite)
NuVatis.Extensions.DependencyInjection Microsoft DI 통합 + Health Check
NuVatis.Extensions.OpenTelemetry OpenTelemetry 분산 추적 (ActivitySource)
NuVatis.Extensions.EntityFrameworkCore EF Core DbContext 커넥션/트랜잭션 공유
NuVatis.Extensions.Aspire .NET Aspire 통합 (Health Check + OTel 자동 구성)
NuVatis.Testing 테스트 지원 (InMemorySqlSession, QueryCapture)

Quick Start

Installation

dotnet add package NuVatis.Core
dotnet add package NuVatis.Generators
dotnet add package NuVatis.PostgreSql
dotnet add package NuVatis.Extensions.DependencyInjection

Mapper Interface

public interface IUserMapper {
    User? GetById(int id);
    Task<User?> GetByIdAsync(int id, CancellationToken ct = default);
    IList<User> Search(UserSearchParam param);
    int Insert(User user);
    int Update(User user);
    int Delete(int id);
}

XML Mapper

<?xml version="1.0" encoding="utf-8" ?>
<mapper namespace="Sample.Mappers.IUserMapper">

  <cache eviction="LRU" flushInterval="600000" size="512" />

  <resultMap id="UserResult" type="User">
    <id column="id" property="Id" />
    <result column="user_name" property="UserName" />
    <result column="email" property="Email" />
  </resultMap>

  <select id="GetById" resultMap="UserResult">
    SELECT id, user_name, email FROM users WHERE id = #{Id}
  </select>

  <select id="Search" resultMap="UserResult">
    SELECT id, user_name, email FROM users
    <where>
      <if test="UserName != null">
        AND user_name LIKE #{UserName}
      </if>
      <foreach collection="Ids" item="id"
               open="AND id IN (" separator="," close=")">
        #{id}
      </foreach>
    </where>
  </select>

  <insert id="Insert">
    INSERT INTO users (user_name, email) VALUES (#{UserName}, #{Email})
  </insert>

</mapper>

C# Attribute (Static SQL)

public interface IUserMapper {
    [Select("SELECT id, user_name, email FROM users WHERE id = #{Id}")]
    [ResultMap("UserResult")]
    User? GetById(int id);

    [Insert("INSERT INTO users (user_name, email) VALUES (#{UserName}, #{Email})")]
    int Insert(User user);
}

DI Integration (ASP.NET Core)

builder.Services.AddNuVatis(options => {
    options.ConnectionString = builder.Configuration.GetConnectionString("Default");
    options.Provider         = new PostgreSqlProvider();
    options.RegisterMappers(NuVatisMapperRegistry.RegisterAll);
    options.RegisterAttributeStatements(NuVatisMapperRegistry.RegisterAttributeStatements);
});

builder.Services.AddHealthChecks().AddNuVatis();

Usage

public class UserService {
    private readonly IUserMapper _mapper;

    public UserService(IUserMapper mapper) {
        _mapper = mapper;
    }

    public async Task<User?> GetUser(int id) {
        return await _mapper.GetByIdAsync(id);
    }
}

Manual Session (Non-DI)

using var session = factory.OpenSession();
var mapper = session.GetMapper<IUserMapper>();

var user = mapper.GetById(1);
mapper.Insert(newUser);
session.Commit();

Session Lifecycle

Environment Registration Lifecycle
ASP.NET Core (DI) Scoped Per HTTP request
Generic Host (DI) Scoped Per scope
Console/Batch Manual using block
  • autoCommit: false (default) - MyBatis 호환. Commit 없이 Dispose 시 자동 Rollback
  • autoCommit: true - 각 쿼리 후 즉시 커밋
  • Lazy Connection - 첫 쿼리 시점에 DB 연결 개시

Transaction Management

using var session = factory.OpenSession();
var mapper = session.GetMapper<IUserMapper>();

mapper.Insert(user);
mapper.Insert(order);
session.Commit();

ExecuteInTransactionAsync:

await session.ExecuteInTransactionAsync(async () => {
    await mapper.InsertAsync(user);
    await mapper.InsertAsync(order);
});

Streaming (IAsyncEnumerable)

대용량 결과를 메모리에 모두 적재하지 않고 스트리밍으로 소비한다.

await foreach (var row in session.SelectStream<StatRow>("Stats.GetAll")) {
    Process(row);
}

Multi-ResultSet

하나의 SQL에서 반환되는 여러 결과셋을 순차 소비한다.

await using var results = await session.SelectMultipleAsync("Dashboard.Overview", param);
var summary = await results.ReadAsync<DashboardSummary>();
var details = await results.ReadListAsync<DashboardDetail>();
var trends  = await results.ReadListAsync<TrendData>();

Second-Level Cache

Namespace 단위 LRU 캐시. Select 시 캐시 히트하면 DB를 건너뛴다. Insert/Update/Delete 실행 시 해당 namespace 캐시를 자동 무효화한다.

XML 설정:

<cache eviction="LRU" flushInterval="600000" size="512" />

<select id="GetMonthlyStats" resultMap="StatsResult" useCache="true">
    SELECT ... FROM monthly_stats WHERE month = #{Month}
</select>

ICacheProvider 인터페이스를 통해 Redis 등 외부 캐시로 교체 가능하다.

EF Core Integration

EF Core와 동일 트랜잭션 내에서 NuVatis 쿼리를 실행한다. DbConnection/DbTransaction을 자동 공유한다.

builder.Services.AddNuVatis(options => { ... });
builder.Services.AddNuVatisEntityFrameworkCore<AppDbContext>();

수동 사용:

await using var nuvatisSession = await dbContext.OpenNuVatisSessionAsync(factory);
var stats = await nuvatisSession.SelectListAsync<MonthlyStats>("Stats.GetMonthly");

Interceptors

SQL 실행 전후에 횡단 관심사를 처리한다.

Prometheus Metrics (내장)

factory.AddInterceptor(new MetricsInterceptor());

Meter "NuVatis": nuvatis.query.total, nuvatis.query.duration, nuvatis.query.errors.total

OpenTelemetry Tracing

factory.AddInterceptor(new OpenTelemetryInterceptor());

ActivitySource "NuVatis.SqlSession" 기반 분산 추적. 태그: db.system, db.statement, db.operation, otel.status_code

Health Check (ASP.NET Core)

builder.Services.AddHealthChecks().AddNuVatis();

SELECT 1 핑 쿼리로 DB 연결 상태를 검증한다. __nuvatis_health Statement가 자동 등록된다.

CommandTimeout

Statement 단위로 SQL 실행 타임아웃을 설정할 수 있다. 우선순위: Statement > Session Default.

<select id="HeavyReport" commandTimeout="120">
    SELECT ... FROM large_table ...
</select>

Dynamic SQL Tags

Tag Description
<if test="..."> 조건부 SQL
<choose>/<when>/<otherwise> Switch-case
<where> 자동 WHERE 절 처리
<set> 자동 SET 절 처리
<foreach> 컬렉션 반복
<bind> 변수 바인딩 (OGNL 표현식)
<sql>/<include> SQL 프래그먼트 재사용

External Connection Sharing

외부에서 관리하는 DbConnection/DbTransaction을 NuVatis에서 사용할 수 있다. 커넥션/트랜잭션 수명 관리는 외부 호출자에 위임된다.

using var session = factory.FromExistingConnection(connection, transaction);
var data = session.SelectList<Item>("Items.GetAll");

Testing

var session = new InMemorySqlSession();
session.Setup("UserMapper.GetById", expectedUser);

var result = session.SelectOne<User>("UserMapper.GetById");

Assert.True(QueryCapture.HasQuery(session, "UserMapper.GetById"));
Assert.Equal(1, QueryCapture.QueryCount(session, "UserMapper.GetById"));

Custom DB Provider

[NuVatisProvider("CustomDb")]
public class CustomDbProvider : IDbProvider {
    public string Name => "CustomDb";
    public DbConnection CreateConnection(string connectionString)
        => new CustomDbConnection(connectionString);
    public string ParameterPrefix => "@";
    public string GetParameterName(int index) => $"@p{index}";
    public string WrapIdentifier(string name) => $"\"{name}\"";
}

XML Schema Validation

NuVatis.Core 패키지에 XML 스키마 파일이 포함되어 있다. IDE에서 XML 매퍼 작성 시 자동완성 및 유효성 검사에 활용할 수 있다.

<?xml version="1.0" encoding="utf-8" ?>
<mapper namespace="..."
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="schemas/nuvatis-mapper.xsd">
Schema Description
schemas/nuvatis-mapper.xsd Mapper XML 스키마 (select, insert, update, delete, resultMap, cache, dynamic SQL)
schemas/nuvatis-config.xsd Configuration XML 스키마

Build & Test

dotnet build
dotnet test

Pack (수동):

dotnet pack --configuration Release --output ./nupkg

Pack (스크립트):

./pack.sh                       # Directory.Build.props 버전 사용
./pack.sh 1.0.1                 # 버전 지정

pack.sh는 빌드, 테스트, 패키징, 11개 패키지 검증을 자동 수행한다.

CI/CD

GitHub Actions 기반 CI/CD 파이프라인:

Workflow Trigger 역할
ci.yml push (main, develop), PR 빌드, 테스트, 코드 커버리지, 패키지 생성 검증
publish.yml v* 태그 push 빌드, 테스트, NuGet.org 배포, GitHub Release 생성
benchmark.yml push (main), PR BenchmarkDotNet 성능 벤치마크 실행 및 회귀 감지
e2e-testcontainers.yml push (main), PR Testcontainers 기반 PostgreSQL/MySQL 멀티버전 E2E 테스트
docs.yml push (main, docs/**) DocFX 문서 빌드 및 GitHub Pages 배포

NuGet 배포는 Trusted Publishing (OIDC) 방식을 사용한다. API 키를 저장하지 않고, GitHub Actions가 발급하는 단기 OIDC 토큰으로 NuGet.org 임시 API 키를 획득하여 배포한다.

릴리스 방법:

git tag v1.0.0
git push origin v1.0.0

태그 push 시 publish.yml이 자동 실행되어 11개 패키지를 NuGet.org에 배포하고 GitHub Release를 자동 생성한다.

Project Structure

NuVatis.sln
Directory.Build.props              # 공통 NuGet 메타데이터 + 버전
pack.sh                            # NuGet 패키징 스크립트
schemas/
  nuvatis-mapper.xsd                 # Mapper XML 스키마
  nuvatis-config.xsd                 # Config XML 스키마
src/
  NuVatis.Core/                      # 핵심 런타임
  NuVatis.Generators/                # Roslyn Source Generator
  NuVatis.PostgreSql/                # PostgreSQL Provider
  NuVatis.MySql/                     # MySQL/MariaDB Provider
  NuVatis.SqlServer/                 # SQL Server Provider
  NuVatis.Sqlite/                    # SQLite Provider
  NuVatis.Extensions.DependencyInjection/  # DI + Health Check
  NuVatis.Extensions.OpenTelemetry/  # OpenTelemetry 분산 추적
  NuVatis.Extensions.EntityFrameworkCore/  # EF Core 통합
  NuVatis.Extensions.Aspire/         # .NET Aspire 통합
  NuVatis.Testing/                   # 테스트 유틸리티
tests/
  NuVatis.Tests/                     # 단위/통합/E2E 테스트 (311개)
  NuVatis.Generators.Tests/          # Source Generator 테스트 (68개)
benchmarks/
  NuVatis.Benchmarks/                # 성능 벤치마크
samples/
  NuVatis.Sample/                    # 사용 예제

Requirements

  • .NET 7.0+ (.NET 7 / .NET 8 멀티 타겟)
  • C# 11+

License

MIT License. Copyright (c) 2026 Jinho Choi.

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
2.5.0 62 3/12/2026
2.4.0 79 3/9/2026
2.3.0 82 3/5/2026
2.2.0 77 3/5/2026
2.1.0 90 2/28/2026
2.0.0 86 2/26/2026
1.0.4 85 2/26/2026
0.1.0-alpha.1 47 2/25/2026