.net enterprise micro-ORM
- Simple
- Fast
- Convention-based
- DB agnostic
- Object mapping library
- Where objects can be defined as
- With
- Rich functionality
- L1 cache support
- Fast serialization
- Binary - very small footprint, one of the fastest and most compact binary serializers
- XML - fast XML serializer supporting both element and attribute based serialization
- JSON - one of the fastest JSON serializers
- Unit of work implementation
- Immutable read-only DTO's
- Extensive configuration options
- Declarative validation
- Data type conversion options (handling enumerations, nullable types, DBNull values, type coercion)
- Key generation options
- Active Record through extension methods
- LINQ Provider
- Asynchronous programming
- Async methods
- Async LINQ Provider
- Targeting .Net 4.7.2 and .Net Standard 2.0
Install NuGet package
Nemo is a .NET Enterprise Micro-ORM (Object-Relational Mapping) library that provides a lightweight, fast, and convention-based approach to database operations. It targets .NET Framework 4.7.2, .NET Standard 2.0, and .NET Standard 2.1.
The codebase follows a modular, layered architecture with clear separation of concerns:
Nemo/
├── src/Nemo/ # Main library code
├── tests/ # Test projects
│ ├── Nemo.Test/ # Unit tests
│ ├── Nemo.Test.Core/ # Core functionality tests
│ └── Nemo.Benchmark/ # Performance benchmarks
└── Nemo.sln # Visual Studio solution
- Location:
ObjectFactory.cs
+ partial classes - Purpose: Central hub for all ORM operations
- Key Operations: Create, Map, Insert, Update, Delete, Retrieve
- Features:
- Object instantiation and mapping
- Batch operations
- Transaction support
- Type conversion and coercion
- Location:
Configuration/
folder - Key Interface:
INemoConfiguration
- Features:
- Connection string management
- Caching configuration
- SQL generation settings
- Logging and audit configuration
- Materialization modes
- Location:
Data/
folder - Key Components:
DialectProvider
: Database-specific SQL generationDbFactory
: Connection managementSqlBuilder
: Dynamic SQL construction- Supported Databases: SQL Server, MySQL, PostgreSQL, Oracle, SQLite
- Location:
Reflection/
folder - Key Classes:
FastMapper
: High-performance object mappingFastActivator
: Optimized object creationAdapter
: Interface implementationReflector
: Metadata extraction
- Performance: Uses compiled expressions and IL generation for speed
- Location:
Linq/
folder - Components:
NemoQueryProvider
: LINQ query executionNemoQueryable
: Queryable implementation- Features: Both sync and async LINQ support
- Location:
Serialization/
folder - Formats Supported:
- Binary: Compact, high-performance
- JSON: Fast JSON serialization
- XML: Element and attribute-based
- Location:
Collections/
folder - Features:
- Custom collection types optimized for ORM scenarios
- Eager loading support
- Async enumerable implementations
- Location:
Validation/
folder - Features:
- Declarative validation attributes
- Custom validation support
- Integration with data annotations
- Location:
UnitOfWork/
folder - Features:
- Change tracking
- Transaction scoping
- Object state management
Application Code
↓
ObjectFactory (Entry Point)
↓
Configuration → Reflection/Mapping → Data Access
↓ ↓ ↓
Settings Object Mapping SQL Generation
↓ ↓ ↓
Caching ← Serialization ← Database Provider
↓
Database
- Factory Pattern:
ObjectFactory
for object creation and operations - Provider Pattern: Database dialect providers for multi-DB support
- Strategy Pattern: Different serialization and mapping strategies
- Unit of Work: Transaction and change tracking management
- Repository Pattern: Abstracted data access operations
- Compiled Expressions: Fast property access and mapping
- IL Generation: Dynamic method creation for optimal performance
- Caching: Multiple levels of metadata and result caching
- Batch Operations: Efficient bulk insert/update operations
- Connection Pooling: Optimized database connection management
- .NET Multi-targeting: Framework 4.7.2, Standard 2.0/2.1
- System.Data: Core data access
- System.Interactive: Async LINQ support
- Microsoft.Extensions: Configuration and DI integration
- Reflection.Emit: Dynamic code generation
The library uses attributes for declarative configuration:
[Table]
: Table mapping[MapColumn]
: Column mapping[PrimaryKey]
: Primary key designation[DoNotPersist]
: Exclude from persistence[References]
: Foreign key relationships
- Start with:
ObjectFactory.cs
- understand core operations - Configuration:
INemoConfiguration.cs
- see available settings - Data Access:
DialectProvider.cs
- understand DB abstraction - Mapping:
Reflection/FastMapper.cs
- see how objects are mapped - Examples: Check
tests/
folder for usage patterns
- Performance: Optimized for speed with compiled expressions
- Flexibility: Supports classes and interfaces as DTOs
- Database Agnostic: Works with multiple database providers
- Rich Features: Caching, validation, serialization, LINQ
- Convention-based: Minimal configuration required
- Async Support: Full async/await pattern support
This architecture makes Nemo a powerful yet lightweight ORM that balances performance, flexibility, and ease of use for enterprise .NET applications.
The false dilemma that's been holding back enterprise .NET development for too long
If you've been developing .NET applications for any length of time, you've probably found yourself caught in this familiar dilemma:
Option A: Choose Dapper for blazing-fast performance, but sacrifice productivity features like change tracking, validation, and rich LINQ support.
Option B: Choose Entity Framework for developer productivity and rich features, but accept the performance overhead that comes with it.
This choice has become so ingrained in our industry that we've started to believe it's inevitable. Performance or productivity. Speed or features. Pick your poison.
But what if this is a false choice?
Let's be honest about what these compromises actually cost us:
- ✅ Lightning-fast queries
- ✅ Minimal overhead
- ❌ Manual SQL everywhere
- ❌ No change tracking
- ❌ Limited validation support
- ❌ Repetitive mapping code
- ❌ No built-in caching
- ✅ Rich LINQ support
- ✅ Change tracking
- ✅ Migrations
- ✅ Validation integration
- ❌ Performance overhead
- ❌ Complex configuration
- ❌ Memory consumption
- ❌ Query translation limitations
The result? Teams either burn developer hours writing boilerplate code, or they burn CPU cycles and memory on features they don't always need.
Here's what actually happens in enterprise environments:
- You start with EF Core because productivity matters for rapid development
- Performance issues emerge as data volume grows
- You optimize the hot paths by dropping down to Dapper
- Now you maintain two different patterns in the same codebase
- Complexity explodes as you manage different approaches for different scenarios
Sound familiar? You're not alone. According to the 2024 Stack Overflow Developer Survey, performance remains one of the top concerns for enterprise developers, yet productivity tools like ORMs continue to dominate adoption.
What if you could get:
- Dapper-level performance through compiled expressions and optimized mapping
- Enterprise-grade features like caching, validation, and Unit of Work
- Multi-database support without vendor lock-in
- Convention-based simplicity that doesn't sacrifice flexibility
- Both sync and async patterns throughout
This isn't theoretical. It's exactly what Nemo delivers.
We ran comprehensive benchmarks using BenchmarkDotNet - the gold standard for .NET performance testing - against a SQL Server 2022 database to provide transparent, reproducible performance comparisons. Here are the actual results:
Test Environment:
- AMD EPYC, 8 cores, .NET 8.0.18
- SQL Server 2022 with Northwind customer data
- BenchmarkDotNet v0.15.2 with ColdStart strategy
Performance Results (Select All Operations):
Approach | Median Time | Operations/sec | Memory Allocated |
---|---|---|---|
Entity Framework Core | 1,232 μs | 353 ops/sec | 101.12 KB |
Native ADO.NET | 434 μs | 2,157 ops/sec | 1.55 KB |
Native + Nemo Mapper | 448 μs | 1,868 ops/sec | 4.54 KB |
Dapper | 439 μs | 1,889 ops/sec | 3.76 KB |
Nemo Execute | 423 μs | 2,140 ops/sec | 2.73 KB |
Nemo Retrieve | 479 μs | 1,754 ops/sec | 5.07 KB |
Nemo Select | 511 μs | 1,555 ops/sec | 7.92 KB |
Performance Results (Select By Id Operations):
Approach | Median Time | Operations/sec | Memory Allocated |
---|---|---|---|
Entity Framework Core | 1,395 μs | 322 ops/sec | 103.91 KB |
Native ADO.NET | 409 μs | 2,182 ops/sec | 4.12 KB |
Native + Nemo Mapper | 445 μs | 1,835 ops/sec | 4.68 KB |
Dapper | 443 μs | 1,804 ops/sec | 3.78 KB |
Nemo Execute | 463 μs | 1,921 ops/sec | 5.56 KB |
Nemo Retrieve | 491 μs | 1,675 ops/sec | 5.92 KB |
Nemo Select | 717 μs | 1,165 ops/sec | 13.28 KB |
1. Nemo's Sweet Spot Confirmed The results demonstrate exactly what we promised: Nemo bridges the gap between raw ADO.NET speed and EF Core productivity:
- vs Entity Framework Core: Nemo is 3-4x faster with 95% less memory allocation
- vs Raw ADO.NET: Nemo's mapping adds only 3-9% overhead while providing full object mapping
- vs Dapper: Nemo matches Dapper's speed while offering enterprise features like caching, validation, and Unit of Work
2. Memory Efficiency Advantage Nemo's compiled expression approach delivers exceptional memory efficiency:
- Entity Framework Core: 101-104 KB per operation
- Native + Nemo Mapper: 4.54-4.68 KB per operation (95% less than EF Core)
- Dapper: 3.76-3.78 KB per operation
- Native ADO.NET: 1.55-4.12 KB per operation
3. Enterprise Scale Impact At enterprise scale, these differences are transformative:
- vs EF Core: 3x faster response times, 20x less memory pressure
- 10,000 requests/sec: Nemo saves ~9 seconds vs EF Core per batch
- Memory pressure: 95% reduction in GC pressure vs EF Core
- Throughput: 5x more operations per second than EF Core
Rather than cherry-picking favorable numbers, we're showing you the complete picture. The benchmark project is publicly available so you can:
- Run the benchmarks yourself against your own data
- Verify performance claims in your specific environment
- Test with your actual query patterns
- Compare across different database providers
The bottom line: Nemo delivers on its promise of not making you choose between performance and productivity. You get enterprise features with performance that's closer to raw ADO.NET than to traditional ORMs.
Consider a typical enterprise scenario: an e-commerce platform processing thousands of orders per minute.
With the traditional approach:
- Use EF Core for CRUD operations (developer productivity)
- Drop to Dapper for reporting queries (performance)
- Maintain separate caching layer
- Custom validation logic scattered throughout
- Different patterns for different teams
With Nemo:
- Single ORM handles both scenarios efficiently
- Built-in caching reduces database load
- Declarative validation keeps business rules centralized
- Consistent patterns across the entire application
- Performance that scales with your business
Nemo achieves this balance through several key innovations:
Instead of reflection-heavy mapping, Nemo generates optimized IL code at runtime. Your object mapping runs at near-native speed.
Multiple levels of caching (metadata, query plans, results) mean you pay the compilation cost once and reap the benefits everywhere.
Native support for SQL Server, PostgreSQL, MySQL, Oracle, and SQLite means you're never locked into a single vendor.
Need validation? It's there. Want Unit of Work? Built-in. Don't need serialization? It doesn't slow you down.
The best part? You don't need to rewrite your entire application overnight.
Start small:
- Identify a performance-critical component
- Replace the data access layer with Nemo
- Measure the improvement
- Gradually expand usage
Migration is straightforward:
- From Dapper: Keep your SQL, add enterprise features
- From EF Core: Keep your models, gain performance
- From ADO.NET: Keep your control, add productivity
The choice between performance and productivity is a relic of the past. Modern enterprise applications demand both, and modern tools should deliver both.
Stop compromising. Stop maintaining dual patterns. Stop choosing between speed and features.
Your applications deserve better. Your team deserves better. Your users definitely deserve better.
Try Nemo in your next project:
dotnet add package Nemo
// It's really this simple
var customers = ObjectFactory.Select<Customer>()
.Where(c => c.IsActive)
.ToList();
// With built-in caching, validation, and performance
Learn more:
Because the best choice is not having to choose at all.
Have you been caught in the performance vs productivity dilemma? Share your experiences in the comments below, or reach out on GitHub to discuss how Nemo might fit into your architecture.