Siemens.AspNet.DbProvider 0.1.0-alpha.139

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

Siemens.AspNet.DbProvider

A powerful, flexible database provider for .NET applications that simplifies database interactions with multiple database systems.

Features

  • Multi-Database Support: Works with multiple database providers including:

    • MySQL/MariaDB
    • Snowflake
    • SingleStore (limited support)
  • Type-Safe Queries: Strongly-typed query results with automatic mapping between database and .NET types

  • Dynamic Data Operations:

    • Create, read, update, and delete table data
    • Dynamic table schema management
    • Copy tables and data between tables
  • Transaction Support: Full transaction support across all database providers

  • Parameterized Queries: Protection against SQL injection through parameterized queries

  • SQL Analytics: Built-in query analytics and performance monitoring

  • File Import: Read data from CSV and Excel files with built-in form file readers

  • Data Export: Export data and schema definitions to CSV and Excel formats

  • Migration Support: Database migration utilities for schema evolution

  • Error Handling: Comprehensive error handling with detailed exception information

Installation

Prerequisites

  • .NET 9.0 or higher
  • Required database client libraries:
    • MySQL: MySql.Data package (included as dependency)
    • Snowflake: Snowflake.Data package (included as dependency)

NuGet Package

dotnet add package Siemens.AspNet.DbProvider

Getting Started

Basic Setup

Register the database provider in your Program.cs or startup class:

// Add base services
builder.Services.AddDbProvider(builder.Configuration);

// Add specific provider(s) you need
builder.Services.AddMySqlProvider(builder.Configuration);
// and/or
builder.Services.AddSnowflakeProvider(builder.Configuration);

// If using MySQL, add connection factory
builder.Services.AddMySqlConnectionFactory();

// If using dynamic data features
builder.Services.AddDatabaseService(builder.Configuration);

// If using form file readers (CSV, Excel)
builder.Services.AddFormFileReaderProvider();

// If using data export features
builder.Services.AddDataExporter();
builder.Services.AddSchemaExporter();

Connection String Configuration

In your appsettings.json file:

{
  "ConnectionStrings": {
    "MySqlConnection": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;",
    "SnowflakeConnection": "account=myAccount;user=myUser;password=myPassword;DB=myDatabase;SCHEMA=mySchema;"
  }
}

Basic Usage

Executing Queries
public class UserRepository
{
    private readonly IDbQueryProvider _dbQueryProvider;

    public UserRepository(IDbQueryProvider dbQueryProvider)
    {
        _dbQueryProvider = dbQueryProvider;
    }

    public async Task<User> GetUserByIdAsync(int userId)
    {
        const string sql = "SELECT * FROM Users WHERE Id = @UserId";
        var parameters = new { UserId = userId };
        
        return await _dbQueryProvider.QueryFirstOrDefaultAsync<User>(sql, parameters);
    }
    
    public async Task<IEnumerable<User>> GetAllUsersAsync()
    {
        const string sql = "SELECT * FROM Users";
        
        return await _dbQueryProvider.QueryAsync<User>(sql);
    }
    
    public async Task<int> CreateUserAsync(User user)
    {
        const string sql = "INSERT INTO Users (Name, Email) VALUES (@Name, @Email); SELECT LAST_INSERT_ID();";
        var parameters = new { user.Name, user.Email };
        
        return await _dbQueryProvider.ExecuteScalarAsync<int>(sql, parameters);
    }
}
Using Transactions
public async Task TransferFundsAsync(int fromAccountId, int toAccountId, decimal amount)
{
    using var transaction = await _dbQueryProvider.BeginTransactionAsync();
    
    try
    {
        await _dbQueryProvider.ExecuteAsync(
            "UPDATE Accounts SET Balance = Balance - @Amount WHERE Id = @FromId", 
            new { Amount = amount, FromId = fromAccountId },
            transaction);
            
        await _dbQueryProvider.ExecuteAsync(
            "UPDATE Accounts SET Balance = Balance + @Amount WHERE Id = @ToId", 
            new { Amount = amount, ToId = toAccountId },
            transaction);
            
        await transaction.CommitAsync();
    }
    catch
    {
        await transaction.RollbackAsync();
        throw;
    }
}

Dynamic Data Features

The Dynamic Data module provides powerful schema-agnostic database operations without writing SQL:

Service Registration

// Register the DatabaseService 
builder.Services.AddDatabaseService(builder.Configuration);

Table Schema Management

public class SchemaService
{
    private readonly IDatabaseService _databaseService;
    private readonly DbConnectionInfo _dbConnectionInfo;

    public SchemaService(IDatabaseService databaseService, IDbTypeProvider dbTypeProvider, IConfiguration configuration)
    {
        _databaseService = databaseService;
        
        // Create connection info
        var dbProvider = dbTypeProvider.GetFor(DatabaseProvider.MySql);
        _dbConnectionInfo = dbProvider.ParseConnectionString(
            configuration.GetConnectionString("MySqlConnection"));
    }

    // Create a new table with specified columns
    public async Task<SimplifiedTableSchema> CreateProductTableAsync()
    {
        // Define columns for the table
        var columns = new List<SimpleColumn>
        {
            new("Id", SimplifiedDbType.Integer) { IsPrimaryKey = true, IsAutoIncrement = true },
            new("ProductName", SimplifiedDbType.String) { MaxLength = 100, IsNullable = false },
            new("Description", SimplifiedDbType.String) { MaxLength = 500 },
            new("Price", SimplifiedDbType.Decimal) { IsNullable = false },
            new("CreatedAt", SimplifiedDbType.DateTime) { IsNullable = false },
            new("IsActive", SimplifiedDbType.Bool) { IsNullable = false, DefaultValue = "1" }
        };

        // Create the table
        return await _databaseService.AddTableAsync(
            "Products", 
            columns.ToImmutableList(), 
            _dbConnectionInfo);
    }
    
    // Add a column to existing table
    public async Task<int> AddCategoryColumnAsync()
    {
        // Get table schema
        var tableSchema = await _databaseService.GetTableSchemaAsync(
            "Products", 
            _dbConnectionInfo);
            
        // Add column
        return await _databaseService.AddColumnToAsync(
            tableSchema,
            new SimpleColumn("Category", SimplifiedDbType.String) { MaxLength = 50 });
    }
    
    // Copy table structure (with or without data)
    public async Task<SimplifiedTableSchema> CreateProductsBackupTableAsync()
    {
        // Get existing table schema
        var existingTable = await _databaseService.GetTableSchemaAsync(
            "Products", 
            _dbConnectionInfo);
            
        // Create copy with data
        return await _databaseService.CopyTableAsync(
            "Products_Backup",
            existingTable,
            copyData: true);
    }
}

Dynamic CRUD Operations

public class ProductRepository
{
    private readonly IDatabaseService _databaseService;
    private readonly SimplifiedTableSchema _tableSchema;

    public ProductRepository(IDatabaseService databaseService)
    {
        _databaseService = databaseService;
        
        // This would be retrieved once and cached/injected in a real app
        _tableSchema = databaseService.GetTableSchemaAsync("Products", connectionInfo).Result;
    }

    // Insert data
    public async Task<InsertDataResult> AddProductsAsync(IEnumerable<Dictionary<string, object>> products)
    {
        // Convert to dynamic data objects
        var dynamicData = new DynamicDataObjectsWithLocation(products);
        
        // Add audit values
        var auditValues = new Dictionary<string, string>
        {
            { "CreatedAt", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") },
            { "IsActive", "1" }
        }.ToImmutableDictionary();
        
        // Insert data
        return await _databaseService.InsertDataAsync(_tableSchema, dynamicData, auditValues);
    }
    
    // Query data with filtering
    public async Task<IEnumerable<ProductDto>> GetActiveProductsAsync()
    {
        // Create where condition
        var wherePart = new WherePart();
        wherePart.AddEqualCondition("IsActive", "1");
        
        // Define sort order
        var sortOrder = new SortOrder("ProductName", ColumnSortOrder.Asc);
        
        // Get data with specific columns
        return await _databaseService.GetDataAsync<ProductDto>(
            _tableSchema,
            wherePart,
            sortOrder,
            "Id", "ProductName", "Price", "Category");
    }
    
    // Query with pagination
    public async Task<PageInfo<ProductDto>> GetProductsPagedAsync(int pageNumber, int pageSize)
    {
        // Create pagination
        var pagination = new Pagination(pageNumber, pageSize);
        
        // Create sort order
        var sortOrder = new SortOrder("ProductName", ColumnSortOrder.Asc);
        
        // Get paginated data
        return await _databaseService.GetDataPageWiseAsync<ProductDto>(
            _tableSchema,
            pagination,
            new WherePart(),
            sortOrder);
    }
    
    // Update data
    public async Task<UpdateDataResult> UpdateProductPricesAsync(
        IEnumerable<Dictionary<string, object>> productsWithNewPrices)
    {
        // Convert to dynamic data objects
        var dynamicData = new DynamicDataObjectsWithLocation(productsWithNewPrices);
        
        // Add audit values
        var auditValues = new Dictionary<string, string>
        {
            { "ModifiedAt", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") }
        }.ToImmutableDictionary();
        
        // Update data
        return await _databaseService.UpdateDataAsync(_tableSchema, dynamicData, auditValues);
    }
    
    // Delete data by condition
    public async Task<int> DeleteDiscontinuedProductsAsync(string category)
    {
        var wherePart = new WherePart();
        wherePart.AddEqualCondition("Category", category);
        wherePart.AddEqualCondition("IsActive", "0");
        
        return await _databaseService.DeleteDataAsync(_tableSchema, wherePart);
    }
}

Powerful Data Import and Export

public class DataImportExportService
{
    private readonly IFormFileReaderProvider _fileReaderProvider;
    private readonly IDatabaseService _databaseService;
    private readonly IDbDataExporter _dataExporter;
    private readonly IDbSchemaExporter _schemaExporter;
    private readonly SimplifiedTableSchema _tableSchema;

    public DataImportExportService(
        IFormFileReaderProvider fileReaderProvider,
        IDatabaseService databaseService,
        IDbDataExporter dataExporter,
        IDbSchemaExporter schemaExporter)
    {
        _fileReaderProvider = fileReaderProvider;
        _databaseService = databaseService;
        _dataExporter = dataExporter;
        _schemaExporter = schemaExporter;
        
        // This would be retrieved once and cached/injected in a real app
        _tableSchema = databaseService.GetTableSchemaAsync("Products", connectionInfo).Result;
    }

    // Import products from CSV file
    public async Task<InsertDataResult> ImportProductsFromCsvAsync(IFormFile csvFile)
    {
        // Get CSV reader
        var reader = _fileReaderProvider.GetReader(FormFileReaderInfo.CsvReader);
        
        // Read data as dynamic objects
        var products = await reader.ReadAsDynamicObjectsAsync(csvFile);
        
        // Insert into database
        return await _databaseService.InsertDataAsync(_tableSchema, products);
    }
    
    // Export data to CSV file
    public async Task ExportProductsToCsvAsync(string filePath)
    {
        // Get product data
        var data = await _databaseService.GetDataAsync<Dictionary<string, object>>(
            _tableSchema,
            "*");
            
        // Export to CSV
        await _dataExporter.ExportAsync(
            _tableSchema.TableName,
            data,
            filePath,
            DbDataExporterInfo.CsvExporter);
    }
    
    // Export schema to Excel
    public async Task ExportSchemaToExcelAsync(string filePath)
    {
        await _schemaExporter.ExportAsync(
            _tableSchema,
            filePath,
            DbSchemaExporterInfo.ExcelExporter);
    }
}

Advanced Features

SQL Analytics

The provider includes SQL analytics that can help you monitor and optimize your queries:

// Enable SQL analytics in your configuration
public void ConfigureServices(IServiceCollection services)
{
    services.AddMySqlAnalyticsHandler(Configuration);
    // ... other services
}

// Use analytics-enabled methods
public class PerformanceMonitoringService
{
    private readonly IDbQueryProvider _dbQueryProvider;
    
    public PerformanceMonitoringService(IDbQueryProvider dbQueryProvider)
    {
        _dbQueryProvider = dbQueryProvider;
    }
    
    public async Task<QueryPerformanceInfo> GetUserDataWithPerformanceMetrics(int userId)
    {
        var sql = @"
            SELECT u.*, p.* 
            FROM Users u
            JOIN UserProfiles p ON u.Id = p.UserId
            WHERE u.Id = @UserId";
            
        var (users, metrics) = await _dbQueryProvider.QueryWithAnalyticsAsync<UserWithProfile>(
            sql, 
            new { UserId = userId });
            
        // Return both query results and performance metrics
        return new QueryPerformanceInfo
        {
            Data = users,
            ExecutionTimeMs = metrics.ExecutionTime.TotalMilliseconds,
            RowsAffected = metrics.RowCount,
            SqlExecuted = metrics.FormatedSql
        };
    }
}

Logging and Error Handling

The provider offers comprehensive logging and error handling:

public class DataAccessService
{
    private readonly IDbQueryProvider _dbQueryProvider;
    private readonly ILogger<DataAccessService> _logger;
    
    public DataAccessService(IDbQueryProvider dbQueryProvider, ILogger<DataAccessService> logger)
    {
        _dbQueryProvider = dbQueryProvider;
        _logger = logger;
    }
    
    public async Task<IEnumerable<User>> GetUsersWithLoggingAsync()
    {
        const string sql = "SELECT * FROM Users";
        
        try
        {
            // Execute query with logging
            var (users, logs) = await _dbQueryProvider.QueryWithLogAsync<User>(sql);
            
            // Log query information
            _logger.LogInformation(
                "Query executed successfully: {SqlQuery}, Rows: {RowCount}, Time: {ExecutionTimeMs}ms",
                logs.FormatedSql,
                logs.RowCount,
                logs.ExecutionTime.TotalMilliseconds);
                
            return users;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error executing query");
            throw;
        }
    }
}

Database Types Support

The provider supports various database types:

MySQL Types

  • String types: varchar, tinytext, text, mediumtext, longtext, etc.
  • Numeric types: int, tinyint, smallint, bigint, decimal, float, double
  • Date/time types: datetime, date, timestamp, time, year
  • Boolean type
  • JSON type

Snowflake Types

  • String types: varchar, string, text
  • Numeric types: integer, smallint, bigint, decimal, float, double
  • Date/time types: datetime, date, time, timestamp
  • Boolean type
  • JSON type

Simplified Database Types

For cross-database compatibility, the library provides simplified types:

// Simplified types abstract the actual database type
public enum SimplifiedDbType
{
    String,
    Integer,
    Decimal,
    Bool,
    DateTime,
    Date,
    Json
}

// Example using simplified types to create a table
var columns = new List<SimpleColumn>
{
    new("Id", SimplifiedDbType.Integer) { IsPrimaryKey = true, IsAutoIncrement = true },
    new("Name", SimplifiedDbType.String) { MaxLength = 100 },
    new("IsActive", SimplifiedDbType.Bool),
    new("CreatedAt", SimplifiedDbType.DateTime),
    new("Config", SimplifiedDbType.Json)
};

Contributing

Contributions to the Siemens.AspNet.DbProvider are welcome. Please ensure that your code adheres to the existing style and includes appropriate tests.

License

Copyright 2025 (c) Siemens AG. All rights reserved.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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
0.1.0-alpha.274 0 9/2/2025
0.1.0-alpha.273 46 9/1/2025
0.1.0-alpha.272 27 9/1/2025
0.1.0-alpha.271 151 8/29/2025
0.1.0-alpha.270 142 8/29/2025
0.1.0-alpha.269 141 8/29/2025
0.1.0-alpha.268 147 8/29/2025
0.1.0-alpha.267 150 8/27/2025
0.1.0-alpha.266 175 8/27/2025
0.1.0-alpha.264 194 8/22/2025
0.1.0-alpha.263 66 8/22/2025
0.1.0-alpha.262 69 8/22/2025
0.1.0-alpha.261 81 8/22/2025
0.1.0-alpha.260 88 8/22/2025
0.1.0-alpha.259 90 8/22/2025
0.1.0-alpha.258 238 8/19/2025
0.1.0-alpha.257 188 8/18/2025
0.1.0-alpha.246 148 8/14/2025
0.1.0-alpha.245 113 8/14/2025
0.1.0-alpha.244 151 8/14/2025
0.1.0-alpha.243 118 8/14/2025
0.1.0-alpha.238 123 8/12/2025
0.1.0-alpha.237 424 8/6/2025
0.1.0-alpha.236 223 8/5/2025
0.1.0-alpha.235 195 8/5/2025
0.1.0-alpha.234 199 8/5/2025
0.1.0-alpha.233 163 8/4/2025
0.1.0-alpha.232 179 8/4/2025
0.1.0-alpha.231 68 8/1/2025
0.1.0-alpha.230 72 8/1/2025
0.1.0-alpha.229 92 7/31/2025
0.1.0-alpha.228 90 7/31/2025
0.1.0-alpha.227 94 7/31/2025
0.1.0-alpha.225 90 7/31/2025
0.1.0-alpha.224 101 7/30/2025
0.1.0-alpha.222 179 7/16/2025
0.1.0-alpha.219 159 7/14/2025
0.1.0-alpha.217 77 7/11/2025
0.1.0-alpha.212 167 7/8/2025
0.1.0-alpha.211 154 7/3/2025
0.1.0-alpha.207 111 7/3/2025
0.1.0-alpha.206 289 6/30/2025
0.1.0-alpha.205 90 6/27/2025
0.1.0-alpha.202 89 6/27/2025
0.1.0-alpha.200 93 6/27/2025
0.1.0-alpha.198 93 6/27/2025
0.1.0-alpha.196 99 6/27/2025
0.1.0-alpha.195 92 6/27/2025
0.1.0-alpha.194 91 6/27/2025
0.1.0-alpha.193 93 6/27/2025
0.1.0-alpha.192 96 6/27/2025
0.1.0-alpha.191 94 6/27/2025
0.1.0-alpha.189 116 6/26/2025
0.1.0-alpha.188 167 6/26/2025
0.1.0-alpha.187 109 6/26/2025
0.1.0-alpha.186 128 6/26/2025
0.1.0-alpha.185 112 6/26/2025
0.1.0-alpha.184 118 6/26/2025
0.1.0-alpha.183 116 6/26/2025
0.1.0-alpha.182 112 6/26/2025
0.1.0-alpha.181 127 6/25/2025
0.1.0-alpha.180 125 6/24/2025
0.1.0-alpha.179 116 6/23/2025
0.1.0-alpha.178 196 6/23/2025
0.1.0-alpha.176 118 6/23/2025
0.1.0-alpha.174 124 6/19/2025
0.1.0-alpha.173 157 6/19/2025
0.1.0-alpha.172 121 6/17/2025
0.1.0-alpha.171 166 6/16/2025
0.1.0-alpha.169 115 6/16/2025
0.1.0-alpha.165 270 6/13/2025
0.1.0-alpha.164 224 6/13/2025
0.1.0-alpha.163 229 6/13/2025
0.1.0-alpha.160 260 6/12/2025
0.1.0-alpha.159 349 6/11/2025
0.1.0-alpha.158 268 6/11/2025
0.1.0-alpha.143 262 6/11/2025
0.1.0-alpha.142 261 6/11/2025
0.1.0-alpha.140 271 6/11/2025
0.1.0-alpha.139 267 6/10/2025
0.1.0-alpha.138 244 6/9/2025
0.1.0-alpha.137 48 6/7/2025
0.1.0-alpha.136 48 6/7/2025
0.1.0-alpha.135 84 6/6/2025
0.1.0-alpha.134 82 6/6/2025
0.1.0-alpha.130 127 6/5/2025
0.1.0-alpha.129 125 6/4/2025
0.1.0-alpha.128 117 6/4/2025