diff --git a/util/Seeder/Migration/Databases/IDatabaseImporter.cs b/util/Seeder/Migration/Databases/IDatabaseImporter.cs
new file mode 100644
index 0000000000..6da2da8a66
--- /dev/null
+++ b/util/Seeder/Migration/Databases/IDatabaseImporter.cs
@@ -0,0 +1,92 @@
+namespace Bit.Seeder.Migration.Databases;
+
+///
+/// Interface for database importers that migrate data from SQL Server to various database systems.
+///
+public interface IDatabaseImporter : IDisposable
+{
+ ///
+ /// Establishes a connection to the target database.
+ ///
+ /// True if connection was successful, false otherwise.
+ bool Connect();
+
+ ///
+ /// Closes the connection to the target database.
+ ///
+ void Disconnect();
+
+ ///
+ /// Creates a table in the target database from a schema definition.
+ ///
+ /// Name of the table to create.
+ /// List of column names.
+ /// Dictionary mapping column names to their SQL Server data types.
+ /// Optional list of columns that require special handling (e.g., JSON columns).
+ /// True if table was created successfully, false otherwise.
+ bool CreateTableFromSchema(
+ string tableName,
+ List columns,
+ Dictionary columnTypes,
+ List? specialColumns = null);
+
+ ///
+ /// Retrieves the list of column names for a table.
+ ///
+ /// Name of the table.
+ /// List of column names.
+ List GetTableColumns(string tableName);
+
+ ///
+ /// Imports data into a table.
+ ///
+ /// Name of the target table.
+ /// List of column names in the data.
+ /// Data rows to import.
+ /// Number of rows to import per batch.
+ /// True if import was successful, false otherwise.
+ bool ImportData(
+ string tableName,
+ List columns,
+ List data,
+ int batchSize = 1000);
+
+ ///
+ /// Checks if a table exists in the target database.
+ ///
+ /// Name of the table to check.
+ /// True if table exists, false otherwise.
+ bool TableExists(string tableName);
+
+ ///
+ /// Gets the number of rows in a table.
+ ///
+ /// Name of the table.
+ /// Number of rows in the table.
+ int GetTableRowCount(string tableName);
+
+ ///
+ /// Drops a table from the database.
+ ///
+ /// Name of the table to drop.
+ /// True if table was dropped successfully, false otherwise.
+ bool DropTable(string tableName);
+
+ ///
+ /// Disables foreign key constraints to allow data import without referential integrity checks.
+ ///
+ /// True if foreign keys were disabled successfully, false otherwise.
+ bool DisableForeignKeys();
+
+ ///
+ /// Re-enables foreign key constraints after data import.
+ ///
+ /// True if foreign keys were enabled successfully, false otherwise.
+ bool EnableForeignKeys();
+
+ ///
+ /// Tests the connection to the database.
+ ///
+ /// True if connection test was successful, false otherwise.
+ bool TestConnection();
+}
diff --git a/util/Seeder/Migration/Databases/MariaDbImporter.cs b/util/Seeder/Migration/Databases/MariaDbImporter.cs
index d7baaf7e9c..e3983f9f1f 100644
--- a/util/Seeder/Migration/Databases/MariaDbImporter.cs
+++ b/util/Seeder/Migration/Databases/MariaDbImporter.cs
@@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging;
namespace Bit.Seeder.Migration.Databases;
-public class MariaDbImporter(DatabaseConfig config, ILogger logger) : IDisposable
+public class MariaDbImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter
{
private readonly ILogger _logger = logger;
private readonly string _host = config.Host;
diff --git a/util/Seeder/Migration/Databases/PostgresImporter.cs b/util/Seeder/Migration/Databases/PostgresImporter.cs
index 06c0e88fdd..9d7d58857a 100644
--- a/util/Seeder/Migration/Databases/PostgresImporter.cs
+++ b/util/Seeder/Migration/Databases/PostgresImporter.cs
@@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging;
namespace Bit.Seeder.Migration.Databases;
-public class PostgresImporter(DatabaseConfig config, ILogger logger) : IDisposable
+public class PostgresImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter
{
private readonly ILogger _logger = logger;
private readonly string _host = config.Host;
diff --git a/util/Seeder/Migration/Databases/SqlServerImporter.cs b/util/Seeder/Migration/Databases/SqlServerImporter.cs
index b48c835778..215d8784d9 100644
--- a/util/Seeder/Migration/Databases/SqlServerImporter.cs
+++ b/util/Seeder/Migration/Databases/SqlServerImporter.cs
@@ -6,7 +6,7 @@ using System.Data;
namespace Bit.Seeder.Migration.Databases;
-public class SqlServerImporter(DatabaseConfig config, ILogger logger) : IDisposable
+public class SqlServerImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter
{
private readonly ILogger _logger = logger;
private readonly string _host = config.Host;
diff --git a/util/Seeder/Migration/Databases/SqliteImporter.cs b/util/Seeder/Migration/Databases/SqliteImporter.cs
index 2b81d40372..fd4e13c845 100644
--- a/util/Seeder/Migration/Databases/SqliteImporter.cs
+++ b/util/Seeder/Migration/Databases/SqliteImporter.cs
@@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging;
namespace Bit.Seeder.Migration.Databases;
-public class SqliteImporter(DatabaseConfig config, ILogger logger) : IDisposable
+public class SqliteImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter
{
private readonly ILogger _logger = logger;
private readonly string _databasePath = config.Database;
diff --git a/util/Seeder/Recipes/CsvMigrationRecipe.cs b/util/Seeder/Recipes/CsvMigrationRecipe.cs
index 7f30851ed7..7cbfb0e646 100644
--- a/util/Seeder/Recipes/CsvMigrationRecipe.cs
+++ b/util/Seeder/Recipes/CsvMigrationRecipe.cs
@@ -212,7 +212,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac
return false;
}
- dynamic? importer = CreateImporter(dbType, destConfig);
+ IDatabaseImporter? importer = CreateImporter(dbType, destConfig);
if (importer == null)
{
_logger.LogError("Failed to create importer for {DbType}", dbType);
@@ -354,7 +354,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac
return false;
}
- dynamic? importer = CreateImporter(dbType, destConfig);
+ IDatabaseImporter? importer = CreateImporter(dbType, destConfig);
if (importer == null)
{
_logger.LogError("Failed to create importer for {DbType}", dbType);
@@ -453,7 +453,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac
return false;
}
- dynamic? importer = CreateImporter(dbType, destConfig);
+ IDatabaseImporter? importer = CreateImporter(dbType, destConfig);
if (importer == null)
{
_logger.LogError("Failed to create importer for {DbType}", dbType);
@@ -481,7 +481,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac
}
}
- private dynamic? CreateImporter(string dbType, DatabaseConfig config) =>
+ private IDatabaseImporter? CreateImporter(string dbType, DatabaseConfig config) =>
dbType.ToLower() switch
{
"postgres" or "postgresql" => new PostgresImporter(config, _loggerFactory.CreateLogger()),