Gids voor het implementeren van een C# gegevensmigratietool met versiebeheer en rollback functies
description
Door het implementeren van een C# gegevensmigratietool met versiebeheer en rollback functies, kun je soepelere database-updates garanderen, downtime minimaliseren en gemakkelijk wijzigingen ongedaan maken bij problemen, wat de algehele stabiliteit van je applicatie verbetert.
prompt
try_prompt
Help me een C# gegevensmigratietool te maken die database schema wijzigingen en gegevens transformaties kan beheren. De tool moet versiebeheer ondersteunen om de migratiestatu ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een voorbeeld van hoe je een basis C# gegevensmigratietool kunt opzetten die database schema wijzigingen, gegevens transformaties, versiebeheer en rollback ondersteunt. Deze code is gestructureerd met aandacht voor modulariteit en uitbreidbaarheid.
**Belangrijk:**
- Gebruik een ORM zoals Entity Framework of Dapper voor database interacties.
- Zorg voor een versiebeheer tabel in je database om migratiestatus bij te houden.
- Implementeer migratie scripts en transformaties als aparte klassen of scripts.
---
### Stap 1: Basisstructuur en versiebeheer
Maak een tabel in je database voor migratiestatus:
```sql
CREATE TABLE MigrationHistory (
Id INT PRIMARY KEY IDENTITY(1,1),
MigrationName NVARCHAR(200),
AppliedOn DATETIME,
IsApplied BIT,
Version NVARCHAR(50)
);
```
### Stap 2: C# code voor migratiebeheer
```csharp
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
namespace DataMigrationTool
{
// Interface voor migraties
public interface IMigration
{
string Name { get; }
string Version { get; }
void Up(SqlConnection connection);
void Down(SqlConnection connection);
}
// Voorbeeld migratie: wijziging in schema
public class AddColumnMigration : IMigration
{
public string Name => "AddAgeColumn";
public string Version => "1.0";
public void Up(SqlConnection connection)
{
var cmd = connection.CreateCommand();
cmd.CommandText = "ALTER TABLE Personen ADD Leeftijd INT NULL";
cmd.ExecuteNonQuery();
}
public void Down(SqlConnection connection)
{
var cmd = connection.CreateCommand();
cmd.CommandText = "ALTER TABLE Personen DROP COLUMN Leeftijd";
cmd.ExecuteNonQuery();
}
}
// Migratiebeheer klasse
public class MigrationManager
{
private readonly string _connectionString;
private readonly List<IMigration> _migrations;
public MigrationManager(string connectionString)
{
_connectionString = connectionString;
_migrations = new List<IMigration>();
// Voeg migraties toe
_migrations.Add(new AddColumnMigration());
// Voeg meer migraties toe naarmate de schema's evolueren
}
public void ApplyMigrations()
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
EnsureMigrationHistoryTable(connection);
foreach (var migration in _migrations)
{
if (!IsMigrationApplied(connection, migration))
{
try
{
migration.Up(connection);
LogMigration(connection, migration, true);
Console.WriteLine($"Migratie {migration.Name} toegepast.");
}
catch (Exception ex)
{
Console.WriteLine($"Fout bij toepassen {migration.Name}: {ex.Message}");
break;
}
}
}
}
}
public void RollbackMigration(string migrationName)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
var migration = _migrations.Find(m => m.Name == migrationName);
if (migration != null)
{
try
{
migration.Down(connection);
LogMigration(connection, migration, false);
Console.WriteLine($"Migratie {migration.Name} teruggedraaid.");
}
catch (Exception ex)
{
Console.WriteLine($"Fout bij rollback {migration.Name}: {ex.Message}");
}
}
else
{
Console.WriteLine("Migratie niet gevonden.");
}
}
}
private void EnsureMigrationHistoryTable(SqlConnection connection)
{
var cmd = connection.CreateCommand();
cmd.CommandText = @"
IF OBJECT_ID('MigrationHistory', 'U') IS NULL
CREATE TABLE MigrationHistory (
Id INT PRIMARY KEY IDENTITY(1,1),
MigrationName NVARCHAR(200),
AppliedOn DATETIME,
IsApplied BIT,
Version NVARCHAR(50)
)";
cmd.ExecuteNonQuery();
}
private bool IsMigrationApplied(SqlConnection connection, IMigration migration)
{
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT COUNT(1) FROM MigrationHistory WHERE MigrationName = @name AND IsApplied = 1";
cmd.Parameters.AddWithValue("@name", migration.Name);
return (int)cmd.ExecuteScalar() > 0;
}
private void LogMigration(SqlConnection connection, IMigration migration, bool success)
{
var cmd = connection.CreateCommand();
cmd.CommandText = @"
INSERT INTO MigrationHistory (MigrationName, AppliedOn, IsApplied, Version)
VALUES (@name, @date, @applied, @version)";
cmd.Parameters.AddWithValue("@name", migration.Name);
cmd.Parameters.AddWithValue("@date", DateTime.Now);
cmd.Parameters.AddWithValue("@applied", success);
cmd.Parameters.AddWithValue("@version", migration.Version);
cmd.ExecuteNonQuery();
}
}
}
```
---
### Stap 3: Voorbeeld gebruik
```csharp
class Program
{
static void Main(string[] args)
{
var connectionString = "Data Source=server;Initial Catalog=database;Integrated Security=True";
var manager = new MigrationManager(connectionString);
// Toepassen van nieuwe migraties
manager.ApplyMigrations();
// Rollback voorbeeld
// manager.RollbackMigration("AddAgeColumn");
}
}
```
---
### Samenvatting
- De tool houdt bij welke migraties zijn toegepast via de `MigrationHistory` tabel.
- Migraties worden geïmplementeerd via de `IMigration` interface met `Up` en `Down` methodes.
- De `MigrationManager` verzorgt het toepassen en terugdraaien van migraties en het bijhouden van de status.
- Voeg nieuwe migraties toe door nieuwe klassen te maken die `IMigration` implementeren en deze te registreren.
---
Wil je ook gegevens transformaties en geavanceerdere rollback functies? Laat het weten!
provider: deepseek
model: deepseek-chat
Hier is een complete C# gegevensmigratietool met versiebeheer en rollback-functionaliteit:
## 1. Basismodellen en interfaces
```csharp
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
public enum MigrationDirection
{
Up,
Down
}
public class MigrationRecord
{
public int Version { get; set; }
public string Description { get; set; }
public DateTime AppliedAt { get; set; }
}
public interface IMigration
{
int Version { get; }
string Description { get; }
void Up(IDbConnection connection);
void Down(IDbConnection connection);
}
```
## 2. Migratiebeheerder
```csharp
public class MigrationManager
{
private readonly string _connectionString;
private readonly List<IMigration> _migrations;
public MigrationManager(string connectionString)
{
_connectionString = connectionString;
_migrations = new List<IMigration>();
EnsureMigrationTableExists();
}
public void AddMigration(IMigration migration)
{
_migrations.Add(migration);
}
private void EnsureMigrationTableExists()
{
using var connection = new SqlConnection(_connectionString);
connection.Open();
var command = connection.CreateCommand();
command.CommandText = @"
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = '__MigrationHistory')
CREATE TABLE __MigrationHistory (
Version INT PRIMARY KEY,
Description NVARCHAR(255),
AppliedAt DATETIME2 DEFAULT GETDATE()
)";
command.ExecuteNonQuery();
}
public void MigrateToLatest()
{
var appliedMigrations = GetAppliedMigrations();
var pendingMigrations = _migrations
.Where(m => !appliedMigrations.Any(am => am.Version == m.Version))
.OrderBy(m => m.Version);
using var connection = new SqlConnection(_connectionString);
connection.Open();
foreach (var migration in pendingMigrations)
{
ExecuteMigration(connection, migration, MigrationDirection.Up);
}
}
public void Rollback(int targetVersion)
{
var appliedMigrations = GetAppliedMigrations()
.Where(m => m.Version > targetVersion)
.OrderByDescending(m => m.Version);
using var connection = new SqlConnection(_connectionString);
connection.Open();
foreach (var migrationRecord in appliedMigrations)
{
var migration = _migrations.First(m => m.Version == migrationRecord.Version);
ExecuteMigration(connection, migration, MigrationDirection.Down);
}
}
private void ExecuteMigration(IDbConnection connection, IMigration migration, MigrationDirection direction)
{
using var transaction = connection.BeginTransaction();
try
{
if (direction == MigrationDirection.Up)
{
migration.Up(connection);
RecordMigration(connection, migration, direction);
}
else
{
migration.Down(connection);
RemoveMigrationRecord(connection, migration);
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
private List<MigrationRecord> GetAppliedMigrations()
{
var migrations = new List<MigrationRecord>();
using var connection = new SqlConnection(_connectionString);
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT Version, Description, AppliedAt FROM __MigrationHistory ORDER BY Version";
using var reader = command.ExecuteReader();
while (reader.Read())
{
migrations.Add(new MigrationRecord
{
Version = reader.GetInt32(0),
Description = reader.GetString(1),
AppliedAt = reader.GetDateTime(2)
});
}
return migrations;
}
private void RecordMigration(IDbConnection connection, IMigration migration, MigrationDirection direction)
{
var command = connection.CreateCommand();
command.CommandText = "INSERT INTO __MigrationHistory (Version, Description) VALUES (@Version, @Description)";
var versionParam = command.CreateParameter();
versionParam.ParameterName = "@Version";
versionParam.Value = migration.Version;
command.Parameters.Add(versionParam);
var descParam = command.CreateParameter();
descParam.ParameterName = "@Description";
descParam.Value = migration.Description;
command.Parameters.Add(descParam);
command.ExecuteNonQuery();
}
private void RemoveMigrationRecord(IDbConnection connection, IMigration migration)
{
var command = connection.CreateCommand();
command.CommandText = "DELETE FROM __MigrationHistory WHERE Version = @Version";
var versionParam = command.CreateParameter();
versionParam.ParameterName = "@Version";
versionParam.Value = migration.Version;
command.Parameters.Add(versionParam);
command.ExecuteNonQuery();
}
public void PrintMigrationStatus()
{
var applied = GetAppliedMigrations();
Console.WriteLine("Toegepaste migraties:");
foreach (var migration in applied)
{
Console.WriteLine($" V{migration.Version}: {migration.Description} - {migration.AppliedAt}");
}
}
}
```
## 3. Voorbeeld migraties
```csharp
public class CreateUsersTableMigration : IMigration
{
public int Version => 1;
public string Description => "Creëer gebruikers tabel";
public void Up(IDbConnection connection)
{
var command = connection.CreateCommand();
command.CommandText = @"
CREATE TABLE Users (
Id INT PRIMARY KEY IDENTITY,
Username NVARCHAR(50) NOT NULL UNIQUE,
Email NVARCHAR(100) NOT NULL,
CreatedAt DATETIME2 DEFAULT GETDATE(),
IsActive BIT DEFAULT 1
)";
command.ExecuteNonQuery();
}
public void Down(IDbConnection connection)
{
var command = connection.CreateCommand();
command.CommandText = "DROP TABLE Users";
command.ExecuteNonQuery();
}
}
public class AddUserRolesMigration : IMigration
{
public int Version => 2;
public string Description => "Voeg rolkolom toe aan gebruikers";
public void Up(IDbConnection connection)
{
var command = connection.CreateCommand();
command.CommandText = @"
ALTER TABLE Users
ADD Role NVARCHAR(20) NOT NULL DEFAULT 'User'";
command.ExecuteNonQuery();
}
public void Down(IDbConnection connection)
{
var command = connection.CreateCommand();
command.CommandText = @"
ALTER TABLE Users
DROP COLUMN Role";
command.ExecuteNonQuery();
}
}
public class CreateOrdersTableMigration : IMigration
{
public int Version => 3;
public string Description => "Creëer bestellingen tabel";
public void Up(IDbConnection connection)
{
var command = connection.CreateCommand();
command.CommandText = @"
CREATE TABLE Orders (
Id INT PRIMARY KEY IDENTITY,
UserId INT NOT NULL,
TotalAmount DECIMAL(10,2) NOT NULL,
OrderDate DATETIME2 DEFAULT GETDATE(),
Status NVARCHAR(20) DEFAULT 'Pending',
FOREIGN KEY (UserId) REFERENCES Users(Id)
)";
command.ExecuteNonQuery();
}
public void Down(IDbConnection connection)
{
var command = connection.CreateCommand();
command.CommandText = "DROP TABLE Orders";
command.ExecuteNonQuery();
}
}
```
## 4. Gebruiksvoorbeeld
```csharp
class Program
{
static void Main()
{
const string connectionString = "Server=.;Database=MyAppDb;Trusted_Connection=true;";
var migrationManager = new MigrationManager(connectionString);
// Registreer migraties
migrationManager.AddMigration(new CreateUsersTableMigration());
migrationManager.AddMigration(new AddUserRolesMigration());
migrationManager.AddMigration(new CreateOrdersTableMigration());
Console.WriteLine("Voer migraties uit naar de laatste versie...");
migrationManager.MigrateToLatest();
migrationManager.PrintMigrationStatus();
Console.WriteLine("\nRollback naar versie 1...");
migrationManager.Rollback(1);
migrationManager.PrintMigrationStatus();
Console.WriteLine("\nOpnieuw migreren naar laatste versie...");
migrationManager.MigrateToLatest();
migrationManager.PrintMigrationStatus();
}
}
```
## 5. Geavanceerde functies - Data transformatie migratie
```csharp
public class TransformUserDataMigration : IMigration
{
public int Version => 4;
public string Description => "Transformeer gebruikersdata en voeg admin toe";
public void Up(IDbConnection connection)
{
// Data transformatie: update bestaande gebruikers
var updateCommand = connection.CreateCommand();
updateCommand.CommandText = @"
UPDATE Users
SET Email = LOWER(Email),
Role = 'User'
WHERE Role IS NULL OR Role = ''";
updateCommand.ExecuteNonQuery();
// Nieuwe admin gebruiker toevoegen
var insertCommand = connection.CreateCommand();
insertCommand.CommandText = @"
IF NOT EXISTS (SELECT 1 FROM Users WHERE Username = 'admin')
INSERT INTO Users (Username, Email, Role)
VALUES ('admin', 'admin@example.com', 'Administrator')";
insertCommand.ExecuteNonQuery();
}
public void Down(IDbConnection connection)
{
// Rollback van data transformatie
var deleteCommand = connection.CreateCommand();
deleteCommand.CommandText = "DELETE FROM Users WHERE Username = 'admin'";
deleteCommand.ExecuteNonQuery();
}
}
```
## Belangrijkste kenmerken:
1. **Versiebeheer**: Elke migratie heeft een uniek versienummer
2. **Transactie-ondersteuning**: Migraties worden atomisch uitgevoerd
3. **Rollback-functionaliteit**: Mogelijkheid om terug te gaan naar eerdere versies
4. **Status tracking**: Bijhouden welke migraties zijn toegepast
5. **Data transformaties**: Ondersteuning voor zowel schema wijzigingen als data transformaties
6. **Uitbreidbaar**: Eenvoudig nieuwe migraties toevoegen via de IMigration interface
Deze tool biedt een robuuste basis voor database migratiebeheer in C# applicaties.

