Skip to content

Commit c3886c3

Browse files
authored
Merge pull request #2 from sanamhub/style/beautify
2 parents 7aa1b9f + 39ae968 commit c3886c3

File tree

5 files changed

+175
-58
lines changed

5 files changed

+175
-58
lines changed

Application.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<PackageReference Include="Dapper" Version="2.0.123" />
1313
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
1414
<PackageReference Include="Npgsql" Version="7.0.1" />
15+
<PackageReference Include="Spectre.Console" Version="0.46.0" />
1516
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
1617
</ItemGroup>
1718

Helpers/SpectreConsoleHelper.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Spectre.Console;
2+
3+
namespace Application.Helpers;
4+
5+
internal class SpectreConsoleHelper
6+
{
7+
public static void Log(string message) => Write($"LOG: {message}", _messageTypes[MessageTypeEnum.Log]);
8+
9+
public static void Error(string error) => Write($"ERROR: {error}", _messageTypes[MessageTypeEnum.Error]);
10+
11+
public static void Information(string information) => Write($"INFO: {information}", _messageTypes[MessageTypeEnum.Information]);
12+
13+
public static void Success(string success) => Write($"LOG: {success}", _messageTypes[MessageTypeEnum.Success]);
14+
15+
public static void Warning(string warning) => Write($"WARN: {warning}", _messageTypes[MessageTypeEnum.Warning]);
16+
17+
private static void Write(string message, string color)
18+
{
19+
AnsiConsole.MarkupLine(string.Format("[{0}]{1}[/]", color, message));
20+
}
21+
22+
public static void WriteHeader(string header, Color color)
23+
{
24+
AnsiConsole.Write(new FigletText(header)
25+
.Centered()
26+
.Color(color));
27+
}
28+
29+
#region Privates
30+
31+
private enum MessageTypeEnum
32+
{
33+
Log,
34+
Error,
35+
Information,
36+
Success,
37+
Warning
38+
}
39+
40+
private static readonly Dictionary<MessageTypeEnum, string> _messageTypes = new()
41+
{
42+
[MessageTypeEnum.Log] = "white",
43+
[MessageTypeEnum.Error] = "red",
44+
[MessageTypeEnum.Information] = "blue",
45+
[MessageTypeEnum.Success] = "green",
46+
[MessageTypeEnum.Warning] = "yellow"
47+
};
48+
49+
#endregion
50+
}

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,45 @@
11
# postgresql-to-mssql
2+
3+
Migrate data from postgresql to sql server on the fly!
4+
5+
### Description
6+
7+
This is a .NET console application that handles data migration (data from tables and views) from postgresql to sql server. It aims to make the process of migrating data from one database to another as seamless and easy as possible.
8+
9+
### Motivations
10+
11+
As an open source enthusiast, I noticed the lack of workable open source tools for migrating data between databases, and the high cost of some paid tools. I wanted to make a contribution to the open source community by creating a tool that is both effective and accessible to all.
12+
13+
### Features
14+
- Migrates data from tables and views in PostgreSQL to SQL Server
15+
- Written in .NET for high performance and compatibility with a wide range of systems
16+
- Easy to use console interface
17+
- Open source and free to use
18+
19+
### Getting Started
20+
21+
1. Clone or download the repository
22+
2. Open the solution in Visual Studio
23+
3. Build the solution
24+
4. Run the executable
25+
5. Follow the prompts to configure the migration
26+
27+
### Contributing
28+
29+
If you would like to contribute to this project, please fork the repository and submit a pull request.
30+
31+
### License
32+
33+
This project is licensed under the MIT License
34+
35+
### Acknowledgements
36+
37+
Thank you to the open source community for all of the support and resources that made this project possible.
38+
39+
### Support
40+
41+
If you have any questions or issues, please open an discussion on GitHub or contact me directly.
42+
43+
#### Happy migrating!
44+
45+
<sub>PS. This README is generated by ChatGPT</sub>

Services/Service.cs

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System.Data;
22
using System.Data.SqlClient;
3+
using Application.Helpers;
34
using Application.Providers.Interfaces;
45
using Application.Services.Interfaces;
56
using Application.Validators.Interfaces;
67
using Dapper;
8+
using Spectre.Console;
79

810
namespace Application;
911

@@ -27,60 +29,77 @@ public void Migrate()
2729
{
2830
_validator.ValidateProviders();
2931

30-
using var postgresConnection = _provider.GetPostgresqlConnection();
31-
using var sqlServerConnection = _provider.GetSqlServerConnection();
32-
33-
postgresConnection.Open();
34-
sqlServerConnection.Open();
35-
36-
// get list of schemas
37-
var getSchemasQuery = "SELECT schema_name FROM information_schema.schemata";
38-
var schemas = postgresConnection.Query<string>(getSchemasQuery).ToList();
39-
40-
// remove postgres schemas
41-
schemas.Remove("information_schema");
42-
schemas.Remove("pg_catalog");
43-
schemas.Remove("pg_toast");
44-
45-
foreach (var sourceSchema in schemas)
46-
{
47-
// modify unsupported schemas
48-
string destinationSchema = $"{sourceSchema}_new";
49-
50-
// create schema
51-
var createDestinationSchemaQuery = $"CREATE SCHEMA [{destinationSchema}];";
52-
sqlServerConnection.Execute(createDestinationSchemaQuery);
53-
54-
// get list of tables
55-
var getTablesQuery = $"SELECT table_name FROM information_schema.tables WHERE table_schema = '{sourceSchema}'";
56-
var tables = postgresConnection.Query<string>(getTablesQuery).ToList();
57-
58-
foreach (var table in tables)
32+
SpectreConsoleHelper.WriteHeader("postgresql to mssql", Color.Blue);
33+
SpectreConsoleHelper.Log("Initializing...");
34+
AnsiConsole.Status()
35+
.Spinner(Spinner.Known.Arc)
36+
.SpinnerStyle(Style.Parse("green"))
37+
.Start("Starting the migration...", ctx =>
5938
{
60-
// get the table column's definition
61-
var getColumnsQuery = $"SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '{table}' AND table_schema = '{sourceSchema}'";
62-
var columns = postgresConnection.Query(getColumnsQuery);
63-
64-
// create the table in sql server
65-
var createTableQuery = $"CREATE TABLE {destinationSchema}.{table} (";
66-
createTableQuery += string.Join(", ", columns.Select(c => $"{c.column_name} {MapPostgresToSqlServerType(c.data_type)}"));
67-
createTableQuery += ")";
68-
sqlServerConnection.Execute(createTableQuery);
69-
70-
// fetch data from postgres
71-
var data = postgresConnection.Query<dynamic>($"SELECT * FROM {sourceSchema}.{table}").ToList();
72-
73-
// bulk copy to sql server
74-
using var bulkCopy = new SqlBulkCopy(sqlServerConnection);
75-
var dataTable = ToDataTable(data);
76-
bulkCopy.DestinationTableName = $"[{destinationSchema}].[{table}]";
77-
bulkCopy.WriteToServer(dataTable);
78-
}
79-
}
39+
using var postgresConnection = _provider.GetPostgresqlConnection();
40+
using var sqlServerConnection = _provider.GetSqlServerConnection();
41+
42+
ctx.Status("Fetching postgresql schemas");
43+
ctx.Spinner(Spinner.Known.BouncingBall);
44+
var getSchemasQuery = "SELECT schema_name FROM information_schema.schemata";
45+
var schemas = postgresConnection.Query<string>(getSchemasQuery).ToList();
46+
SpectreConsoleHelper.Log("Fetched schemas from postgresql...");
47+
48+
schemas.Remove("information_schema");
49+
schemas.Remove("pg_catalog");
50+
schemas.Remove("pg_toast");
51+
52+
ctx.Status("Looping through available schemas...");
53+
foreach (var sourceSchema in schemas)
54+
{
55+
string destinationSchema = $"{sourceSchema}_new";
56+
57+
ctx.Status($"Creating [{destinationSchema}] schema in sql server...");
58+
var createDestinationSchemaQuery = $"CREATE SCHEMA [{destinationSchema}];";
59+
sqlServerConnection.Execute(createDestinationSchemaQuery);
60+
SpectreConsoleHelper.Log($"Created [{destinationSchema}] schema in sql server...");
61+
62+
ctx.Status($"Fetching available tables from [{sourceSchema}] schema...");
63+
var getTablesQuery = $"SELECT table_name FROM information_schema.tables WHERE table_schema = '{sourceSchema}'";
64+
var tables = postgresConnection.Query<string>(getTablesQuery).ToList();
65+
SpectreConsoleHelper.Log($"Fetched tables of [{sourceSchema}] schema from postgres");
66+
67+
ctx.Status($"Looping through all tables of [{sourceSchema}] schema...");
68+
foreach (var table in tables)
69+
{
70+
ctx.Status($"Fetching column definition for [{table}] table...");
71+
var getColumnsQuery = $"SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '{table}' AND table_schema = '{sourceSchema}'";
72+
var columns = postgresConnection.Query(getColumnsQuery);
73+
SpectreConsoleHelper.Log($"Fetched column definition for [{table}] table...");
74+
75+
ctx.Status($"Creating table [{destinationSchema}].[{table}] in sql server...");
76+
var createTableQuery = $"CREATE TABLE {destinationSchema}.{table} (";
77+
createTableQuery += string.Join(", ", columns.Select(c => $"{c.column_name} {MapPostgresToSqlServerType(c.data_type)}"));
78+
createTableQuery += ")";
79+
sqlServerConnection.Execute(createTableQuery);
80+
SpectreConsoleHelper.Log($"Created table [{destinationSchema}].[{table}] in sql server...");
81+
82+
ctx.Status($"Fetching data from [{sourceSchema}].[{table}] from postgresql...");
83+
var data = postgresConnection.Query<dynamic>($"SELECT * FROM {sourceSchema}.{table}").ToList();
84+
SpectreConsoleHelper.Log($"Fetched data from [{sourceSchema}].[{table}] table of postgresql...");
85+
86+
ctx.Status("Coverting the data into proper shape before migrating to sql server...");
87+
var dataTable = ToDataTable(data);
88+
SpectreConsoleHelper.Log("Converted data into proper shape...");
89+
90+
ctx.Status($"Transferring data from [blue][{sourceSchema}].[{table}][/] to [green][{destinationSchema}].[{table}][/]");
91+
using var bulkCopy = new SqlBulkCopy(sqlServerConnection);
92+
bulkCopy.DestinationTableName = $"[{destinationSchema}].[{table}]";
93+
bulkCopy.WriteToServer(dataTable);
94+
SpectreConsoleHelper.Success($"Successfully transferred data from [{sourceSchema}].[{table}] to [{destinationSchema}].[{table}]");
95+
}
96+
}
97+
});
98+
SpectreConsoleHelper.WriteHeader("Success!", Color.Green);
8099
}
81100
catch (Exception ex)
82101
{
83-
Console.WriteLine(ex.Message);
102+
AnsiConsole.WriteException(ex);
84103
}
85104
}
86105

Validators/Validator.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Application.Helpers;
33
using Application.Providers.Interfaces;
44
using Application.Validators.Interfaces;
5+
using Spectre.Console;
56

67
namespace Application.Validators;
78

@@ -21,34 +22,36 @@ public void ValidateProviders()
2122
{
2223
if (!IsServerConnected(sqlServerConnection))
2324
{
24-
Console.WriteLine("Invalid SQL Server Connection!");
25+
SpectreConsoleHelper.Warning("Invalid sql server connection..");
26+
SpectreConsoleHelper.Information("Provide the valid sql server connection string...");
27+
AnsiConsole.MarkupLine("[green]PROMPT:[/] [red]sql server connection string sample:[/] [blue]server=serverName; database=databaseName; user=username; password=password;[/]");
2528

26-
Console.WriteLine("Provide the valid SQL Server Connection String...");
2729
var connectionString = Console.ReadLine();
2830
EnvironmentVariableHelper.Set("SqlServerConnectionString", connectionString);
29-
30-
Console.WriteLine("SqlServerConnectionString Set Successfully!");
31+
SpectreConsoleHelper.Success("Sql server connection string set successfully...");
3132

3233
if (!IsServerConnected(sqlServerConnection)) goto sqlServerStart;
3334
}
3435
}
36+
SpectreConsoleHelper.Success("Sql server connected...");
3537

3638
postgreSqlStart:
3739
using (var postgreSqlConnection = _provider.GetPostgresqlConnection())
3840
{
3941
if (!IsServerConnected(postgreSqlConnection))
4042
{
41-
Console.WriteLine("Invalid PostgreSQL Connection!");
43+
SpectreConsoleHelper.Warning("Invalid postgresql connection..");
44+
SpectreConsoleHelper.Information("Provide the valid [green]postgresql connection string");
45+
AnsiConsole.MarkupLine("[green]PROMPT:[/] [red]postgresql connection string sample:[/] [blue]Server=127.0.0.1;Port=5432;Database=databaseName;User Id=postgres;Password=password;[/]");
4246

43-
Console.WriteLine("Provide the valid PostgreSQL Connection String...");
4447
var connectionString = Console.ReadLine();
4548
EnvironmentVariableHelper.Set("PostgresqlConnectionString", connectionString);
46-
47-
Console.WriteLine("PostgresqlConnectionString Set Successfully!");
49+
SpectreConsoleHelper.Success("Postgresql connection string set successfully...");
4850

4951
if (!IsServerConnected(postgreSqlConnection)) goto postgreSqlStart;
5052
}
5153
}
54+
SpectreConsoleHelper.Success("PostgreSQL connected...");
5255
}
5356

5457
#region Private methods

0 commit comments

Comments
 (0)