Лучший шаблон проектирования для методов обработки больших данных

#c# #design-patterns #coding-style

#c# #шаблоны проектирования #стиль кодирования

Вопрос:

У меня есть приложение, которое я рефакторинг и пытаюсь следовать некоторым принципам «чистого кода». У меня есть приложение, которое считывает данные из нескольких разных источников данных и обрабатывает / форматирует эти данные и вставляет их в другую базу данных. У меня есть уровень данных со связанными DTO, репозиториями, интерфейсами и помощниками для каждого источника данных, а также бизнес-уровень с соответствующими объектами, репозиториями и интерфейсами.

Мой вопрос сводится к методу импорта. У меня в основном есть один метод, который систематически вызывает каждый метод бизнес-логики для чтения, обработки и сохранения данных. Необходимо выполнить множество вызовов, и хотя сам метод импорта вообще не обрабатывает данные, метод по-прежнему чрезвычайно велик. Есть ли лучший способ обработки этих данных?

 ICustomer<Customer> sourceCustomerList = new CustomerRepository();
foreach (Customer customer in sourceCustomerList.GetAllCustomers())
{

   // Read Some Data
   DataObject object1 = iSourceDataType1.GetDataByCustomerID(customer.ID)
   // Format and save the Data
   iTargetDataType1.InsertDataType1(object1)

   // Read Some Data

   // Format the Data

   // Save the Data

   //...Rinse and repeat
}
  

Комментарии:

1. Я считаю, что поток данных TPL хорош для таких вещей. он чрезвычайно мощный и отлично подходит для конвейеров данных, которые необходимо обработать

2. Вот некоторые вещи, которые, я думаю, должны быть учтены в вашем вопросе для получения соответствующего ответа. Что произойдет, если возникнет исключение, нужно ли все откатить или просто обработать с самого начала? или продолжить с того места, где вы остановились в процессе? Сколько данных будет обработано? если при чтении вы имеете дело с большими объемами данных, объем памяти вашего приложения на c # резко возрастет.

3. при исключении мне нужно остановиться, выяснить, почему возникло исключение, и либо исправить его в коде, либо в самих данных, и восстановить, где осталось. Поэтому мне нужно отслеживать итерации и иметь возможность указывать, с какой итерации начинать. Я имею дело с большими объемами данных, но только в куче небольших блоков одновременно.

Ответ №1:

Вам следует изучить библиотеку параллельных задач (TPL) и поток данных

 ICustomer<Customer> sourceCustomerList = new CustomerRepository();

var customersBuffer = new BufferBlock<Customer>();
var transformBlock = new TransformBlock<Customer, DataObject>(
    customer => iSourceDataType1.GetDataByCustomerID(customer.ID)
);

// Build your block with TransformBlock, ActionBlock, many more... 
customersBuffer.LinkTo(transformBlock);

// Add all the blocks you need here....

// Then feed the first block or use a custom source
foreach (var c in sourceCustomerList.GetAllCustomers())
    customersBuffer.Post(c)
customersBuffer.Complete();
  

Комментарии:

1. Это выглядит как довольно приятный рабочий процесс, но как мне продолжить для каждого из блока преобразования, если мне нужно?

Ответ №2:

Ваша производительность будет ограничена вводом-выводом, особенно при большом количестве обращений к базам данных на каждой итерации. Поэтому вам необходимо пересмотреть свою архитектуру, чтобы минимизировать ввод-вывод.

Возможно ли переместить все записи ближе друг к другу (возможно, во временной базе данных) в качестве первого прохода, затем выполнить сопоставление записей и форматирование в базе данных в качестве второго прохода, прежде чем считывать их и сохранять там, где они должны быть?

(В качестве примечания, иногда мы увлекаемся DDD и OO, где все «должно» быть объектом. Но это не всегда лучший подход.)