Из дочернего класса вызовите метод базового класса при использовании дочерних полей - PullRequest
0 голосов
/ 10 января 2020

Я создал небольшую программу 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

    }

}

1 Ответ

1 голос
/ 10 января 2020

Прежде всего, вам необходимо полиморфно запустить «ExecuteJob ()», что означает, что поведение «ExeceuteJob» будет отличаться в зависимости от строки подключения источника и назначения. Вы не можете достичь полиморфизма для функции или свойств stati c. Прежде всего, вам необходимо изменить его на метод экземпляра, выбрав ключевые слова "Stati c". Кроме того, поведение базового класса определяется дочерними классами, так что никто не должен иметь возможности создать объект базового класса, чтобы сделать его абстрактным классом. Посмотрите на свой код, у вас есть два поведения, одно для школы, а другое для учителя. Таким образом, вы должны создать два разных дочерних класса, которые наследуют абстрактный базовый класс. За создание объекта со строкой соединения источника и назначения отвечает создание объекта, поэтому передайте его конструктору и задайте при создании самого объекта. Пожалуйста, найдите измененный код,

public abstract class ETLBase
{
    private readonly string sourceConnectionString;
    private readonly string destinationConnectionString;

    protected virtual string Select { get; set; } = @"Select THIS DataStatement";
    protected virtual string CreateTemp { get; set; } = @"CREATE TABLE Statement";
    protected virtual string Merge { get; set; } = @"Merge Table statement";
    protected virtual string CleanUp { get; set; } = "DROP TABLE Statement";
    protected virtual string DestinationTable { get; set; } = "##TempTable";


    protected ETLBase(string sourceConnectionString, string destinationConnectionString)
    {
        this.sourceConnectionString = sourceConnectionString;
        this.destinationConnectionString = destinationConnectionString;
    }

    public void ExecuteJob()
    {
        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 ChildETLSchool : ETLBase
    {
        public ChildETLSchool(string sourceConnectionString, string destinationConnectionString) 
            : base(sourceConnectionString, destinationConnectionString)
        {
            //Change values of below lines only if you want to override the values

            //Select = @"Select THIS DataStatement";
            //CreateTemp = @"CREATE TABLE Statement";
            //Merge = @"Merge Table statement";
            //CleanUp = "DROP TABLE Statement";
            //DestinationTable = "##TempTable";
        }

    }

    public class ChildETLTeacher : ETLBase
    {
        public ChildETLTeacher(string sourceConnectionString, string destinationConnectionString) 
            : base(sourceConnectionString, destinationConnectionString)
        {
            //Change values of below lines only if you want to override the values

            //Select = @"Select THIS DataStatement";
            //CreateTemp = @"CREATE TABLE Statement";
            //Merge = @"Merge Table statement";
            //CleanUp = "DROP TABLE Statement";
            //DestinationTable = "##TempTable";
        }

    }

И создание объекта в основной функции,

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"];

        var childETLSchool = new ChildETLSchool(schoolDBConnection, courseDBConnection);
        var childETLTeacher = new ChildETLTeacher(teacherDBConnection, courseDBConnection);

        childETLSchool.ExecuteJob();
        childETLTeacher.ExecuteJob();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...