Я создал небольшую программу ETL с одним методом, который принимает только строку подключения для исходной базы данных и строку подключения для целевой базы данных.
По сути, она состоит из 5 шагов:
Шаг 1. Выберите данные из источника.
Шаг 2. Создайте временную таблицу на цели.
Шаг 3. Загрузите данные из источника во временную на цели.
Шаг 4. Объедините данные из временной таблицы в фактическую целевую таблицу.
Шаг 5. Удалите временную таблицу
Это прекрасно работает для одного преобразования, которое необходимо выполнить, но у меня есть около 20 различных "заданий" ETL. это должно иметь место.
Таким образом, вместо того, чтобы копировать и вставлять один и тот же метод дословно 19 раз, я хотел бы определить базовый класс, который определяет этот единственный метод один раз, а затем вызвать этот единственный метод из каждого дочернего класса со своим собственным выбирать, создавать, объединять и удалять заявления.
Возможно ли это?
Базовый класс:
public class ETLBase
{
private static string Select;
private static string CreateTemp;
private static string Merge;
private static string CleanUp;
private static string DestinationTable;
public static void ExecuteJob(string sourceConnectionString, string destinationConnectionString)
{
using (OracleConnection sourceConnection = new OracleConnection(sourceConnectionString))
{
sourceConnection.Open();
OracleCommand selectCommand = new OracleCommand(Select, sourceConnection);
OracleDataReader reader = selectCommand.ExecuteReader();
using (SqlConnection destinationConnection = new SqlConnection(destinationConnectionString))
{
destinationConnection.Open();
SqlCommand createTempCommand = new SqlCommand(CreateTemp, destinationConnection);
createTempCommand.ExecuteNonQuery();
SqlCommand mergeCommand = new SqlCommand(Merge, destinationConnection);
SqlCommand dropCommand = new SqlCommand(CleanUp, destinationConnection);
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection))
{
bulkCopy.DestinationTableName = DestinationTable;
try
{
bulkCopy.WriteToServer(reader);
mergeCommand.ExecuteNonQuery();
dropCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
reader.Close();
}
}
}
}
}
}
Дочерний класс:
public class ChildETL: ETLBase
{
private static string Select = @"Select THIS DataStatement";
private static string CreateTemp = @"CREATE TABLE Statement";
private static string Merge = @"Merge Table statement";
private static string CleanUp = "DROP TABLE Statement";
private static string DestinationTable = "##TempTable";
}
И затем выполнить его примерно так, но где каждый дочерний класс использует свои собственные определенные поля, поэтому он использует свои собственные SQL операторов.
public class Program
{
public static void Main(string[] args)
{
IConfiguration config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.Build();
string schoolDBConnection = config["SchoolConnection"];
string courseDBConnection = config["CourseConnection"];
string teacherDBConnection = config["Connection"];
ChildETLA.ExecuteJob(schoolDBConnection, courseDBConnection);
ChildETLB.ExecuteJob(teacherDBConnection, courseDBConnection);
//...and so on for each child ETL class
}
}