Siemens.AspNet.DbProvider 0.1.0-alpha.303

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.303
                    
NuGet\Install-Package Siemens.AspNet.DbProvider -Version 0.1.0-alpha.303
                    
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.303" />
                    
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.303" />
                    
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.303
                    
#r "nuget: Siemens.AspNet.DbProvider, 0.1.0-alpha.303"
                    
#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.303
                    
#: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.303&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Siemens.AspNet.DbProvider&version=0.1.0-alpha.303&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.309 95 10/31/2025
0.1.0-alpha.307 88 10/31/2025
0.1.0-alpha.306 89 10/31/2025
0.1.0-alpha.305 127 10/27/2025
0.1.0-alpha.303 505 10/22/2025
0.1.0-alpha.302 119 10/21/2025
0.1.0-alpha.301 109 10/21/2025
0.1.0-alpha.300 183 10/20/2025
0.1.0-alpha.299 73 10/18/2025
0.1.0-alpha.298 56 10/18/2025
0.1.0-alpha.297 60 10/18/2025
0.1.0-alpha.296 61 10/18/2025
0.1.0-alpha.294 85 10/17/2025
0.1.0-alpha.293 218 10/8/2025
0.1.0-alpha.292 113 10/8/2025
0.1.0-alpha.290 125 10/8/2025
0.1.0-alpha.289 118 10/7/2025
0.1.0-alpha.284 140 10/7/2025
0.1.0-alpha.283 204 9/19/2025
0.1.0-alpha.282 660 9/19/2025
0.1.0-alpha.281 289 9/16/2025
0.1.0-alpha.280 256 9/16/2025
0.1.0-alpha.279 254 9/16/2025
0.1.0-alpha.278 257 9/16/2025
0.1.0-alpha.275 177 9/3/2025
0.1.0-alpha.274 366 9/2/2025
0.1.0-alpha.273 204 9/1/2025
0.1.0-alpha.272 124 9/1/2025
0.1.0-alpha.271 171 8/29/2025
0.1.0-alpha.270 157 8/29/2025
0.1.0-alpha.269 157 8/29/2025
0.1.0-alpha.268 162 8/29/2025
0.1.0-alpha.267 165 8/27/2025
0.1.0-alpha.266 191 8/27/2025
0.1.0-alpha.264 203 8/22/2025
0.1.0-alpha.263 73 8/22/2025
0.1.0-alpha.262 78 8/22/2025
0.1.0-alpha.261 90 8/22/2025
0.1.0-alpha.260 97 8/22/2025
0.1.0-alpha.259 98 8/22/2025
0.1.0-alpha.258 257 8/19/2025
0.1.0-alpha.257 195 8/18/2025
0.1.0-alpha.246 156 8/14/2025
0.1.0-alpha.245 122 8/14/2025
0.1.0-alpha.244 160 8/14/2025
0.1.0-alpha.243 126 8/14/2025
0.1.0-alpha.238 133 8/12/2025
0.1.0-alpha.237 434 8/6/2025
0.1.0-alpha.236 230 8/5/2025
0.1.0-alpha.235 203 8/5/2025
0.1.0-alpha.234 207 8/5/2025
0.1.0-alpha.233 173 8/4/2025
0.1.0-alpha.232 188 8/4/2025
0.1.0-alpha.231 79 8/1/2025
0.1.0-alpha.230 83 8/1/2025
0.1.0-alpha.229 99 7/31/2025
0.1.0-alpha.228 101 7/31/2025
0.1.0-alpha.227 104 7/31/2025
0.1.0-alpha.225 99 7/31/2025
0.1.0-alpha.224 112 7/30/2025
0.1.0-alpha.222 312 7/16/2025
0.1.0-alpha.219 169 7/14/2025
0.1.0-alpha.217 87 7/11/2025
0.1.0-alpha.212 175 7/8/2025
0.1.0-alpha.211 174 7/3/2025
0.1.0-alpha.207 121 7/3/2025
0.1.0-alpha.206 302 6/30/2025
0.1.0-alpha.205 100 6/27/2025
0.1.0-alpha.202 98 6/27/2025
0.1.0-alpha.200 104 6/27/2025
0.1.0-alpha.198 103 6/27/2025
0.1.0-alpha.196 110 6/27/2025
0.1.0-alpha.195 101 6/27/2025
0.1.0-alpha.194 100 6/27/2025
0.1.0-alpha.193 102 6/27/2025
0.1.0-alpha.192 104 6/27/2025
0.1.0-alpha.191 101 6/27/2025
0.1.0-alpha.189 127 6/26/2025
0.1.0-alpha.188 174 6/26/2025
0.1.0-alpha.187 117 6/26/2025
0.1.0-alpha.186 137 6/26/2025
0.1.0-alpha.185 123 6/26/2025
0.1.0-alpha.184 128 6/26/2025
0.1.0-alpha.183 125 6/26/2025
0.1.0-alpha.182 123 6/26/2025
0.1.0-alpha.181 134 6/25/2025
0.1.0-alpha.180 151 6/24/2025
0.1.0-alpha.179 123 6/23/2025
0.1.0-alpha.178 215 6/23/2025
0.1.0-alpha.176 124 6/23/2025
0.1.0-alpha.174 141 6/19/2025
0.1.0-alpha.173 164 6/19/2025
0.1.0-alpha.172 127 6/17/2025
0.1.0-alpha.171 174 6/16/2025
0.1.0-alpha.169 122 6/16/2025
0.1.0-alpha.165 368 6/13/2025
0.1.0-alpha.164 232 6/13/2025
0.1.0-alpha.163 234 6/13/2025
0.1.0-alpha.160 267 6/12/2025
0.1.0-alpha.159 355 6/11/2025
0.1.0-alpha.158 276 6/11/2025
0.1.0-alpha.143 268 6/11/2025
0.1.0-alpha.142 269 6/11/2025
0.1.0-alpha.140 278 6/11/2025
0.1.0-alpha.139 273 6/10/2025
0.1.0-alpha.138 250 6/9/2025
0.1.0-alpha.137 53 6/7/2025
0.1.0-alpha.136 54 6/7/2025
0.1.0-alpha.135 89 6/6/2025
0.1.0-alpha.134 87 6/6/2025
0.1.0-alpha.130 134 6/5/2025
0.1.0-alpha.129 131 6/4/2025
0.1.0-alpha.128 122 6/4/2025