![]() |
VOOZH | about |
dotnet add package CG.Infrastructure.Data --version 3.10.12
NuGet\Install-Package CG.Infrastructure.Data -Version 3.10.12
<PackageReference Include="CG.Infrastructure.Data" Version="3.10.12" />
<PackageVersion Include="CG.Infrastructure.Data" Version="3.10.12" />Directory.Packages.props
<PackageReference Include="CG.Infrastructure.Data" />Project file
paket add CG.Infrastructure.Data --version 3.10.12
#r "nuget: CG.Infrastructure.Data, 3.10.12"
#:package CG.Infrastructure.Data@3.10.12
#addin nuget:?package=CG.Infrastructure.Data&version=3.10.12Install as a Cake Addin
#tool nuget:?package=CG.Infrastructure.Data&version=3.10.12Install as a Cake Tool
A comprehensive data access library that provides database migration, data access patterns, and repository interfaces using DbUp and Dapper for .NET applications.
CG.Infrastructure.Data is a specialized library that provides robust data access capabilities, database migration management, and repository pattern interfaces. It leverages DbUp for database schema management and Dapper for high-performance data access, offering a foundation for data persistence in .NET applications.
Note: This library provides interfaces and infrastructure components. Concrete implementations of repositories, database seeding, and connection management must be provided by consuming applications.
dotnet add package CG.Infrastructure.Data
Or add the following to your .csproj file:
<PackageReference Include="CG.Infrastructure.Data" Version="3.10.11" />
Add configuration to your appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyApp;Trusted_Connection=true;",
"ReadOnlyConnection": "Server=localhost;Database=MyAppReadOnly;Trusted_Connection=true;"
},
"DbUpOptions": {
"UseDocker": false,
"DbSchema": "dbo",
"Drop": false,
"Ensure": true,
"Journal": "__SchemaVersions",
"ScriptPath": "C:\\Scripts\\Database",
"UseLocal": false,
"DbPath": "C:\\Databases",
"DbInitialSize": "10MB",
"DbMaxSize": "100MB",
"DbFileGrowth": "10MB"
},
"DbOptions": {
"CommandTimeout": 3000,
"GetLastInsertId": "SELECT @@IDENTITY;"
}
}
In your Program.cs or Startup.cs:
using Infrastructure.Data.Extensions;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register data services
builder.Services.RegisterInfraDataServices(builder.Configuration);
var app = builder.Build();
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
private readonly IDataAccess _dataAccess;
public UsersController(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
[HttpGet("custom")]
public async Task<ActionResult<IEnumerable<User>>> GetUsersCustom()
{
var query = "SELECT * FROM Users WHERE IsActive = @IsActive";
var parameters = new { IsActive = true };
var users = await _dataAccess.LoadData<User, object>(
query, parameters, "DefaultConnection");
return Ok(users);
}
}
The library provides comprehensive database migration capabilities:
// Get migration service
var migrationService = serviceProvider.GetRequiredService<IDbMigrationService>();
// Configure scripts to run
var scripts = new List<ScriptConfig>
{
new ScriptConfig
{
Folder = "Initial",
Scripts = ScriptEnum.FileSystem,
AlwaysRun = true
},
new ScriptConfig
{
Folder = "Updates",
Scripts = ScriptEnum.ExecutingAssembly,
AlwaysRun = false
}
};
// Run migrations
var success = migrationService.UpgradeDatabase(scripts);
Direct SQL execution with full transaction support:
// Load data
var users = await _dataAccess.LoadData<User, object>(
"SELECT * FROM Users WHERE Department = @Department",
new { Department = "IT" },
"DefaultConnection"
);
// Load single record
var user = await _dataAccess.LoadSingle<User, object>(
"SELECT * FROM Users WHERE Id = @Id",
new { Id = 1 },
"DefaultConnection"
);
// Execute commands
var affectedRows = await _dataAccess.SaveData(
"INSERT INTO Users (Name, Email) VALUES (@Name, @Email)",
new { Name = "John Doe", Email = "john@example.com" },
"DefaultConnection"
);
// Get scalar values
var userId = await _dataAccess.SaveScalar(
"INSERT INTO Users (Name, Email) VALUES (@Name, @Email); SELECT @@IDENTITY;",
new { Name = "Jane Doe", Email = "jane@example.com" },
"DefaultConnection"
);
Full transaction support for complex operations:
// Start transaction
using var transaction = _dataAccess.StartTransaction("DefaultConnection");
try
{
// Execute multiple operations in transaction
var userResult = await _dataAccess.SaveDataInTransaction(
"INSERT INTO Users (Name, Email) VALUES (@Name, @Email)",
new { Name = "John Doe", Email = "john@example.com" },
transaction
);
var profileResult = await _dataAccess.SaveDataInTransaction(
"INSERT INTO UserProfiles (UserId, Bio) VALUES (@UserId, @Bio)",
new { UserId = userResult, Bio = "Software Developer" },
transaction
);
// Commit transaction
_dataAccess.CommitTransaction(transaction);
}
catch
{
// Rollback on error
_dataAccess.RollbackTransaction(transaction);
throw;
}
The library provides the IRepository<T> interface. You must implement concrete repository classes:
// Example implementation - you must create this class
public class UserRepository : IRepository<User>
{
private readonly IDataAccess _dataAccess;
public UserRepository(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public async Task<IEnumerable<User>> GetAllAsync()
{
return await _dataAccess.LoadData<User, object>(
"SELECT * FROM Users", null, "DefaultConnection");
}
public async Task<User?> GetByIdAsync(object id)
{
return await _dataAccess.LoadSingle<User, object>(
"SELECT * FROM Users WHERE Id = @Id",
new { Id = id },
"DefaultConnection"
);
}
public async Task<Guid> CreateAsync(User entity)
{
var result = await _dataAccess.SaveScalar(
"INSERT INTO Users (Name, Email) VALUES (@Name, @Email); SELECT @@IDENTITY;",
entity,
"DefaultConnection"
);
return new Guid(result.ToString());
}
public async Task<bool> UpdateAsync(User entity)
{
var affected = await _dataAccess.SaveData(
"UPDATE Users SET Name = @Name, Email = @Email WHERE Id = @Id",
entity,
"DefaultConnection"
);
return affected > 0;
}
public async Task<bool> DeleteByIdAsync(object id)
{
var affected = await _dataAccess.SaveData(
"DELETE FROM Users WHERE Id = @Id",
new { Id = id },
"DefaultConnection"
);
return affected > 0;
}
// Implement other interface methods...
public async Task<IEnumerable<User>> FindAsync(Expression<Func<User, bool>> predicate)
{
// Implementation depends on your requirements
throw new NotImplementedException("Implement based on your needs");
}
public async Task<bool> ExistsAsync(Expression<Func<User, bool>> predicate)
{
// Implementation depends on your requirements
throw new NotImplementedException("Implement based on your needs");
}
public async Task<bool> DeleteAsync(User entity)
{
return await DeleteByIdAsync(entity.Id);
}
}
Built-in pagination with customizable query generation:
// Configure pagination options
services.RegisterDbOptions(configuration, options =>
{
options.GetPageQuery = (input, pageIndex, pageSize, totalCount, orderBy, pairs) =>
{
var offset = (pageIndex - 1) * pageSize;
return $"{input} {orderBy} OFFSET {offset} ROWS FETCH NEXT {pageSize} ROWS ONLY";
};
});
// Use pagination
public async Task<PagedResult<User>> GetUsersPaged(int page, int pageSize)
{
var offset = (page - 1) * pageSize;
var users = await _dataAccess.LoadData<User, object>(
"SELECT * FROM Users ORDER BY Name OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY",
new { Offset = offset, PageSize = pageSize },
"DefaultConnection"
);
var totalCount = await _dataAccess.LoadSingle<int, object>(
"SELECT COUNT(*) FROM Users",
null,
"DefaultConnection"
);
return new PagedResult<User>(users, totalCount, page, pageSize);
}
| Property | Description | Default |
|---|---|---|
UseDocker |
Flag indicating Docker environment | false |
DbSchema |
Database schema name | "dbo" |
Drop |
Whether to drop existing database | false |
Ensure |
Whether to ensure database exists | false |
Journal |
Schema version table name | "__SchemaVersions" |
ScriptPath |
Path to script files | null |
Collate |
Database collation | "SQL_Latin1_General_CP1_CI_AS" |
UseLocal |
Use local database configuration | false |
DbPath |
Local database file path | null |
DbInitialSize |
Initial database size | null |
DbMaxSize |
Maximum database size | null |
DbFileGrowth |
Database file growth size | null |
LogPath |
Log file path | null |
LogInitialSize |
Initial log size | null |
LogMaxSize |
Maximum log size | null |
LogFileGrowth |
Log file growth size | null |
| Property | Description | Default |
|---|---|---|
ColumnProtect |
Column name protection dictionary | {"left": "[", "right": "]"} |
GetPageQuery |
Custom pagination query function | Built-in SQL Server pagination |
CommandTimeout |
SQL command timeout in milliseconds | 3000 |
GetLastInsertId |
Query to get last insert ID | "SELECT @@IDENTITY;" |
EnableRetryOnFailure |
Enable retry policy for failed operations | false |
MaxRetryCount |
Maximum number of retry attempts | 3 |
RetryInterval |
Retry interval in seconds | 5 |
The library supports multiple script sources through ScriptEnum:
var scripts = new List<ScriptConfig>
{
new ScriptConfig
{
Folder = "Initial",
Scripts = ScriptEnum.FileSystem,
AlwaysRun = true,
Assembly = null
},
new ScriptConfig
{
Folder = "Migrations",
Scripts = ScriptEnum.ExecutingAssembly,
AlwaysRun = false,
Assembly = "MyApp.Data"
}
};
The library provides extension methods for easy service registration:
Registers all data services with configuration:
services.RegisterInfraDataServices(configuration);
This method:
DbUpOptions with configuration bindingDbOptions with configuration bindingImportant: Repository implementations are not automatically registered. You must register them manually or implement the RegisterServices method to scan for implementations.
You can also register individual options manually:
// Register DbUp options
services.RegisterDbUpOptions(configuration, options =>
{
options.UseDocker = true;
options.ScriptPath = "/app/scripts";
});
// Register database options
services.RegisterDbOptions(configuration, options =>
{
options.CommandTimeout = 5000;
options.GetPageQuery = CustomPaginationQuery;
});
IRepository<T> for your entitiesIDatabaseSeedService if neededIConnectionFactory is properly implemented// Register your repository implementations
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IProductRepository, ProductRepository>();
// ... other repositories
services.RegisterDbOptions(configuration, options =>
{
options.GetPageQuery = (input, pageIndex, pageSize, totalCount, orderBy, pairs) =>
{
var offset = (pageIndex - 1) * pageSize;
var limit = pageSize;
// Custom pagination logic
if (pageSize > totalCount)
{
limit = totalCount;
}
return $"{input} {orderBy} LIMIT {limit} OFFSET {offset}";
};
});
Note: You must implement IDatabaseSeedService yourself:
public class DatabaseSeedService : IDatabaseSeedService
{
private readonly IDataAccess _dataAccess;
public DatabaseSeedService(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public async Task ApplySeeding()
{
// Check if seeding is needed
var userCount = await _dataAccess.LoadSingle<int, object>(
"SELECT COUNT(*) FROM Users", null, "DefaultConnection");
if (userCount == 0)
{
// Apply initial seed data
await _dataAccess.SaveData(
"INSERT INTO Users (Name, Email, IsActive) VALUES (@Name, @Email, @IsActive)",
new { Name = "Admin", Email = "admin@example.com", IsActive = true },
"DefaultConnection"
);
}
}
}
// Register the service
services.AddScoped<IDatabaseSeedService, DatabaseSeedService>();
// appsettings.Development.json
{
"DbUpOptions": {
"UseDocker": false,
"ScriptPath": "C:\\DevScripts\\Database"
}
}
// appsettings.Production.json
{
"DbUpOptions": {
"UseDocker": true,
"ScriptPath": "/app/scripts"
}
}
This library integrates with the broader infrastructure suite by:
This library is part of the CG Infrastructure suite. For contributions, please follow the established patterns and ensure all tests pass.
This project is licensed under the terms specified in the LICENSE file.
3.10.11: Current stable release
3.10.8: Previous release
For issues, questions, or contributions, please refer to the project repository or contact the maintainers.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 3 NuGet packages that depend on CG.Infrastructure.Data:
| Package | Downloads |
|---|---|
|
CG.Infrastructure.Mediator
Infra Mediator library with MediatR setup, extensions and database contexts |
|
|
CG.Infrastructure.Authorization
Infra Authorization library with Duende setup, extensions and database contexts |
|
|
CG.Infrastructure.Authentication
Infra Authentication library with AspNetCore.Identity setup, extensions and database contexts |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.10.12 | 167 | 4/1/2026 |
| 3.10.11 | 128 | 2/23/2026 |
| 3.10.10 | 255 | 10/7/2025 |
| 3.10.9 | 324 | 8/20/2025 |
| 3.10.8 | 255 | 8/20/2025 |
| 3.10.7 | 250 | 8/15/2025 |
| 3.10.6 | 251 | 8/10/2025 |
| 3.10.5 | 253 | 6/18/2025 |
| 3.10.4 | 281 | 6/18/2025 |
| 3.10.3 | 376 | 6/9/2025 |
| 3.10.2 | 226 | 6/7/2025 |
| 3.10.1 | 180 | 6/7/2025 |
| 3.10.0 | 223 | 6/6/2025 |
| 3.9.7 | 278 | 3/3/2025 |
| 3.9.6 | 273 | 2/26/2025 |
| 3.9.5 | 287 | 2/11/2025 |
| 3.9.4 | 242 | 2/7/2025 |
| 3.9.3 | 232 | 2/3/2025 |
| 3.9.2 | 240 | 12/10/2024 |
| 3.9.1 | 214 | 12/10/2024 |