Страницы

Поиск по вопросам

вторник, 28 мая 2019 г.

Экспорт модели в .xlsx соблюдая SOLID

В БД есть таблица результатов тестирования по русскому языку и математике (SubjectCode=2)
dbo.Result
Во второй таблице находятся просто сведения о школах:
dbo.School

Таких результатов бывает 40.000-70.000. Нужно на выходе получить для каждого тестируемого вот такой отчет в pdf-файле

Мое решение:
Создал Excel-шаблон; Беру данные из базы и заношу их в этот xlsx-шаблон; Сохраняю этот шаблон в pdf-файл; И так для каждого ученика.

LearnerReport.cs
namespace so16092016.Models { public class LearnerReport { public string SNS { get; set; } //Surname Name SecondName public string SchoolName { get; set; } public string ClassName { get; set; } public int TestResult5 { get; set; } } }
Program.cs
using Excel = Microsoft.Office.Interop.Excel;
namespace so16092016 { class Program { static void Main(string[] args) { resultsEntities context = new resultsEntities(); ResultsRepository resultsRepository = new ResultsRepository(context); var ma_results = resultsRepository.GetTList().Where(x => x.SubjectCode == 2); //получить результаты по математике
Excel.Application app = new Excel.Application(); app.DisplayAlerts = false; Excel.Workbook book_template = app.Workbooks.Open(@"шаблон_отчета.xlsx"); Excel._Worksheet sheet_template = book_template.Sheets["отчет"];
foreach(var ob in ma_results) { //1. Создаем объкт LearnerReport из БД LearnerReport report = new LearnerReport { SNS = $"{ob.surname} {ob.name} {ob.SecondName}", SchoolName = ob.SchoolName, ClassName = ob.ClassName, TestResult5 = ob.TestResult5 };
//2. Экспорт объкта LearnerReport в шаблон xlsx sheet_template.Range["C4"].Value2 = report.SNS; sheet_template.Range["C5"].Value2 = report.SchoolName; sheet_template.Range["C6"].Value2 = report.ClassName; sheet_template.Range["C9"].Value2 = report.TestResult5;
//3. Сохраняем полученный файл в .pdf на рабочем столе string file_name = $@"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\{report.SNS}.pdf"; sheet_template.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, file_name); }
book_template.Close(0); book_template = null; app.Quit(); app = null; } } }
Необходимо: Приложение работает и дает необходимый результат. Но вы наверное видите, что оно далеко от ООП (SOLID) и как результат очень трудно его "допиливать" и масштабировать. Помогите правильно спроектировать данный механизм формирования подобных отчетов:
логика экспорта модели в .xlsx должна быть у самой модели или необходимо создать отдельный класс-менеджер для этого? какие должны быть модели? как правильно создавать модель-отчета на основе объектов БД? какой порождающий паттерн здесь больше подходит?


Ответ

Конкретно в вашем случай нет необходимость, применять какие либо паттерны, т.к. у вас довольно простая программа и паттерны добавят лишь ненужную сложность (применять паттерны ради паттернов плохая практика). Паттерны сгодятся если вы пишите большие Enterprise приложения, где необходима гибкость и масштабируемость.
Если я правильно понял, то вы хотите отрефакторить программу.
1) Из кода я не понял что вы используете для получения данных из БД, но посоветовал бы использовать какую нибудь ORM, например Entity Framework 6
Создать DbContext и использовать его в репозиториях ResultsRepository и SchoolRepository Все выборки засунуть в соответствующий репозиторий например
class ResultsRepository { // возвращает все результаты public IEnumerable GetResults()
// возвращает все результаты по заданому предмету. public IEnumerable GetResults(Subject subject)
// возвращает все результаты для заданой школы. public IEnumerable GetResults(int idSchool)
// возвращает все результаты для заданой школы по заданому предмету. public IEnumerable GetResults(int idSchool, Subject subject) }
class SchoolRepository { // возвращает список всех школ. public IEnumerable GetSchools() }
2) Модель данных приблизительно выглядит так
class Result { [Key] public Guid Id { get; set; }
public string Surname { get; set; } public string Name { get; set; } public string SecondName { get; set; }
[NotMapped] public string SNS => $"{Surname} {Name} {SecondName}";
public School School { get; set; }
public string ClassName { get; set; }
public Subject Subject { get; set; }
public int TestResult5 { get; set; } }
class School { [Key] public int Id { get; set; } public string Name { get; set; } }
enum Subject { RussianLanguage = 1, Mathematics = 2 }
3) Можно создать отдельный класс для работы отчётами
class LearnerReportManager { public Excel._Worksheet CreateReport(Result result)
public SaveReport(Excel._Worksheet reportWorksheet, string fileName) }
4) Для формирования Excel отчёта луче используйте EPPlus или более крутой File Formats от Syncfusion (у них есть бесплатная версия). вы так не будите зависеть от установленного MS Office.
5) Если кол. формируемых отчетов за раз от 40 до 70 тыс., то было бы не плохо добавить многопоточное создание отчетов, это существенно уменьшит время создания отчётов.

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

Отправить комментарий