Rystem.RepositoryFramework.Infrastructure.EntityFramework
10.0.3
See the version list below for details.
dotnet add package Rystem.RepositoryFramework.Infrastructure.EntityFramework --version 10.0.3
NuGet\Install-Package Rystem.RepositoryFramework.Infrastructure.EntityFramework -Version 10.0.3
<PackageReference Include="Rystem.RepositoryFramework.Infrastructure.EntityFramework" Version="10.0.3" />
<PackageVersion Include="Rystem.RepositoryFramework.Infrastructure.EntityFramework" Version="10.0.3" />
<PackageReference Include="Rystem.RepositoryFramework.Infrastructure.EntityFramework" />
paket add Rystem.RepositoryFramework.Infrastructure.EntityFramework --version 10.0.3
#r "nuget: Rystem.RepositoryFramework.Infrastructure.EntityFramework, 10.0.3"
#:package Rystem.RepositoryFramework.Infrastructure.EntityFramework@10.0.3
#addin nuget:?package=Rystem.RepositoryFramework.Infrastructure.EntityFramework&version=10.0.3
#tool nuget:?package=Rystem.RepositoryFramework.Infrastructure.EntityFramework&version=10.0.3
What is Rystem?
Integration with Entity Framework and Repository Framework
This package enables seamless integration between Entity Framework Core and the Repository Framework, allowing you to leverage the Repository pattern with automatic mapping between your Domain Model and Database Model.
Core Concepts
1️⃣ Domain Model vs Database Model
In Domain-Driven Design (DDD), you often have:
- Domain Model (
MappingUser): Your business model with domain logic and clean interfaces - Database Model (
User): The actual Entity Framework entity that maps to your database schema
The Entity Framework integration allows you to work with your domain model while the framework automatically handles mapping to/from the database model.
2️⃣ Configuration Components
DbSet: Database Table Reference
t.DbSet = x => x.Users;
This specifies which DbSet from your Entity Framework context holds the data for this repository. It tells the framework: "Find the data in the Users table through this DbSet property."
References: Related Data Loading
t.References = x => x.Include(x => x.IdGruppos);
These are Entity Framework Include() statements that specify which related entities should be eagerly loaded with your main entity. In this example, whenever you fetch a User, its related IdGruppos collection will automatically be loaded. You can chain multiple includes here.
Why this matters: Without proper references, your related data won't be loaded, causing N+1 query problems.
Translate: Domain-to-Database Model Mapping
builder.Translate<User>()
.With(x => x.Username, x => x.Nome)
.With(x => x.Username, x => x.Cognome)
.With(x => x.Email, x => x.IndirizzoElettronico)
.With(x => x.Groups, x => x.IdGruppos)
.With(x => x.Id, x => x.Identificativo)
.WithKey(x => x, x => x.Identificativo);
This configures how properties are mapped between your domain model and database model:
.With(domainProperty, databaseProperty): Maps individual properties.WithKey(domainKey, databaseKey): Specifies the primary key mapping- Each domain property is mapped to its corresponding database column/property
When to use Translation:
- ✅ Different property names (e.g.,
Username→Nome) - ✅ Different data structures (e.g., entity relationships)
- ✅ Property name conventions differ between domain and database
Two Approaches: Choose Your Path
Approach A: Separate Models (with Translation) - Recommended for DDD
Use different classes for domain and database, with translation configured:
// Domain Model - Clean, business-focused
public class MappingUser
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public List<Group> Groups { get; set; }
}
// Database Model - Maps to actual DB schema
public class User
{
public int Identificativo { get; set; } // Different naming
public string Nome { get; set; }
public string Cognome { get; set; }
public string IndirizzoElettronico { get; set; }
public List<Gruppo> IdGruppos { get; set; } // Different structure
}
// Configuration
services.AddRepository<MappingUser, int>(builder =>
{
builder.WithEntityFramework<MappingUser, int, User, SampleContext>(
t =>
{
t.DbSet = x => x.Users;
t.References = x => x.Include(x => x.IdGruppos);
});
// Map domain model properties to database model properties
builder.Translate<User>()
.With(x => x.Username, x => x.Nome)
.With(x => x.Email, x => x.IndirizzoElettronico)
.With(x => x.Groups, x => x.IdGruppos)
.With(x => x.Id, x => x.Identificativo)
.WithKey(x => x, x => x.Identificativo);
});
Benefits:
- Domain model stays clean and focused on business logic
- Database schema can evolve independently
- Better encapsulation of domain concepts
Approach B: Same Model (No Translation) - Simpler Setup
Use the same class for both domain and database:
// Single Model - Used for both domain and database
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public List<Group> Groups { get; set; }
}
// Configuration - No translation needed!
services.AddRepository<User, int>(builder =>
{
builder.WithEntityFramework<User, int, User, SampleContext>(
t =>
{
t.DbSet = x => x.Users;
t.References = x => x.Include(x => x.Groups);
});
// No Translate() call needed when domain model = database model
});
Benefits:
- Simpler configuration (no mapping overhead)
- Faster setup for small projects
- Less boilerplate code
Trade-offs:
- Domain model is tightly coupled to database schema
- Harder to refactor database without affecting domain logic
Complete Example with Business Logic
services.AddDbContext<SampleContext>(options =>
{
options.UseSqlServer(configuration["ConnectionString:Database"]);
}, ServiceLifetime.Scoped);
services.AddRepository<MappingUser, int>(builder =>
{
// Step 1: Configure Entity Framework
builder.WithEntityFramework<MappingUser, int, User, SampleContext>(
t =>
{
t.DbSet = x => x.Users;
t.References = x => x.Include(x => x.IdGruppos);
});
// Step 2: Configure Translation (if using separate models)
builder.Translate<User>()
.With(x => x.Username, x => x.Nome)
.With(x => x.Username, x => x.Cognome)
.With(x => x.Email, x => x.IndirizzoElettronico)
.With(x => x.Groups, x => x.IdGruppos)
.With(x => x.Id, x => x.Identificativo)
.WithKey(x => x, x => x.Identificativo);
// Step 3: Add Business Logic Interceptors
// See: RepositoryFramework.Abstractions > Business > IRepositoryBusiness
builder.AddBusiness()
.AddBusinessBeforeInsert<MappingUserBeforeInsertBusiness>()
.AddBusinessBeforeInsert<MappingUserBeforeInsertBusiness2>();
});
Now available in Dependency Injection:
public class UserService(IRepository<MappingUser, int> repository)
{
public async Task CreateUserAsync(MappingUser user)
{
// Business interceptors run here automatically
await repository.InsertAsync(user);
}
}
Business Logic Interceptors
Business interceptors run at specific points in the repository lifecycle:
- BeforeInsert: Runs before inserting a new entity
- AfterInsert: Runs after inserting a new entity
- BeforeUpdate: Runs before updating an entity
- AfterUpdate: Runs after updating an entity
- BeforeDelete: Runs before deleting an entity
- AfterDelete: Runs after deleting an entity
- BeforeQuery: Runs before querying entities
See the IRepositoryBusiness interface in RepositoryFramework.Abstractions for detailed documentation on implementing custom business logic.
Key Takeaway:
- Choose Approach A (Separate Models) for enterprise applications following DDD principles
- Choose Approach B (Same Model) for smaller projects prioritizing simplicity
Automated REST API with Rystem.RepositoryFramework.Api.Server
Once your repository is configured, you can automatically expose it as a fully-featured REST API without writing endpoint code:
var builder = WebApplicationBuilder.CreateBuilder(args);
// ... your repository configuration ...
builder.Services.AddApiFromRepositoryFramework()
.WithDescriptiveName("Repository API")
.WithPath("/api")
.WithSwagger()
.WithVersion("v1")
.WithDocumentation()
.WithDefaultCors("http://example.com");
var app = builder.Build();
app.UseApiFromRepositoryFramework()
.WithNoAuthorization();
app.Run();
This automatically generates REST endpoints for all your repositories:
GET /api/mappinguser- List all usersGET /api/mappinguser/{id}- Get user by IDPOST /api/mappinguser- Create userPUT /api/mappinguser/{id}- Update userDELETE /api/mappinguser/{id}- Delete user
Your business interceptors run automatically for each operation!
See Repository API Server Documentation for advanced configuration.
| Product | Versions 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. |
-
net10.0
- Microsoft.EntityFrameworkCore (>= 10.0.2)
- Rystem.RepositoryFramework.Abstractions (>= 10.0.3)
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 |
|---|---|---|
| 10.0.5 | 87 | 2/22/2026 |
| 10.0.4 | 126 | 2/9/2026 |
| 10.0.3 | 113,603 | 1/28/2026 |
| 10.0.1 | 209,092 | 11/12/2025 |
| 9.1.3 | 270 | 9/2/2025 |
| 9.1.2 | 764,426 | 5/29/2025 |
| 9.1.1 | 97,814 | 5/2/2025 |
| 9.0.32 | 186,690 | 4/15/2025 |
| 9.0.31 | 5,782 | 4/2/2025 |
| 9.0.30 | 88,823 | 3/26/2025 |
| 9.0.29 | 9,013 | 3/18/2025 |
| 9.0.28 | 246 | 3/17/2025 |
| 9.0.27 | 231 | 3/16/2025 |
| 9.0.26 | 242 | 3/13/2025 |
| 9.0.25 | 52,115 | 3/9/2025 |
| 9.0.21 | 309 | 3/6/2025 |
| 9.0.20 | 19,590 | 3/6/2025 |
| 9.0.19 | 314 | 3/6/2025 |
| 9.0.18 | 298 | 3/4/2025 |
| 9.0.17 | 231 | 3/1/2025 |