Я создаю приложение, используя Xamarin.Forms, и я сталкиваюсь с очень медленным запросом к данным, которые мне нужно оптимизировать, если это возможно.
Чтобы понять вопрос, я пытаясь создать кадр, мне нужно хорошо объяснить отношения с базой данных. Программное обеспечение для бизнеса, которое я пытаюсь создать, позволяет пользователю распределять сотрудников по рабочим группам и рабочим группам. В целях этого объяснения мы можем игнорировать задания, даже если объекты базы данных включают в себя «задание».
Для ежедневного планирования работы сотрудников я создал kanban, который позволяет пользователю перетаскивать имена сотрудников в экипаж, на который они хотят назначить расписание на день, и по завершении редактирования они используют панель инструментов. кнопки для перехода к следующей дате, которую они хотят запланировать. В фоновом режиме код создает объекты базы данных, которые создают связь между сотрудником, датой и командой.
Для планирования операций изо дня в день я создал планировщик в стиле Ганта с боковой прокруткой, который позволяет пользователю перетаскивать блоки операций на команду на день. В фоновом режиме код создает объекты базы данных, которые создают связь между операцией, датой и командой.
Вот простая версия того, как выглядят объекты базы данных.
public interface IEmployee
{
long? Id { get; set; }
string Name { get; }
string Password { get; set; }
}
public interface ICrewMember
{
long? Id { get; set; }
IEmployee Employee { get; set; }
bool IsLeader { get; set; }
ICrew Crew { get; set; }
DateTime Date { get; set; }
}
public interface IJobSchedule
{
long? Id { get; set; }
IOperation Operation { get; set; }
DateTime Date { get; set; }
ICrew Crew { get; set; }
}
public interface IOperation
{
long? Id { get; set; }
int Priority { get; set; }
}
Таким образом, сложность сценария возникает, когда я хочу найти, какие операции сотрудник был запланирован на. Я должен сначала запросить, чтобы найти объекты расписания сотрудника, создать список команд / дат, для которых они были запланированы, затем получить список графиков работы, которые соответствуют списку дат / экипажей, а затем свести его к отдельный список операций (поскольку операция может быть запланирована на несколько дней). Вот мой текущий код для этого:
public async Task<List<IOperation>> GetOperationsByEmployee(IDataService<IJobSchedule> JobScheduleRepository)
{
JobScheduleRepository = JobScheduleRepository ??
throw new ArgumentNullException(nameof(JobScheduleRepository));
var result = new List<IOperation>();
var empSchedMatches = await GetEmployeeSchedules().ConfigureAwait(false);
var jobSchedules = await GetJobSchedules(JobScheduleRepository, empSchedMatches).ConfigureAwait(false);
result = jobSchedules.Select(x => x.Operation).Distinct().ToList();
return result;
}
private async Task<IEnumerable<ICrewMember>> GetEmployeeSchedules()
{
//Get complete list of employee schedules to sort through
var allEmpSched = await CrewMemberRepository.GetItemsAsync().ConfigureAwait(false);
//Get schedules with date greater than or equal to Date for this employee
var empSchedMatches = allEmpSched.Where(x => x.Date >= Date && x.Employee == Employee);
return empSchedMatches;
}
private async Task<IEnumerable<IJobSchedule>> GetJobSchedules(IDataService<IJobSchedule> JobScheduleRepository, IEnumerable<ICrewMember> employeeSchedules)
{
//Get complete list of job schedules to sort through
var allJobSched = await JobScheduleRepository.GetItemsAsync().ConfigureAwait(false);
allJobSched = allJobSched.Where(x => x.Date >= Date && x.Crew != null && x.Operation != null);
int count = allJobSched.Count();
var result = new List<IJobSchedule>();
foreach (var empSched in employeeSchedules)
{
//For each employee schedule, there should be 1 matching job schedule
//if the crew was assigned a job for that day
var matches = allJobSched.Where(x => x.Date == empSched.Date && x.Crew == empSched.Crew);
result.AddRange(matches);
string message = $"GetJobSchedules() comparing ({count}) Job Schedules " +
$"to empSched.{empSched.Id} crew.{empSched.Crew.Id} date.{empSched.Date:M/d}";
System.Diagnostics.Debug.WriteLine(message);
}
return result;
}
Для того, чтобы попытаться просмотреть процесс, я добавил несколько разных битов кода, которые выводили шаги в отладчик , включая секундомер. Вот вывод отладчика:
[0:] Method Called: GetOperationsByEmployee
[0:] GetOperationsByEmployee() executing query...
[0:] Method Called: GetEmployeeSchedules
[0:] Method Called: GetJobSchedules
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.17196 crew.3 date.2/6
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.18096 crew.3 date.2/4
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.18221 crew.3 date.2/3
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.18902 crew.3 date.2/7
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.21243 crew.3 date.1/27
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.21321 crew.3 date.1/28
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.21360 crew.3 date.1/29
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.21399 crew.3 date.1/30
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.21438 crew.3 date.1/31
[0:] GetJobSchedules() comparing (51) Job Schedules to empSched.21528 crew.3 date.2/5
[0:] Data loaded 6391 ms
Так что, когда я запускаю приложение, используя фиктивные данные с примерно 10 объектами в памяти, оно запускается за ~ 100 мс. Когда у меня есть 50 000 объектов в реальной базе данных с 30 сотрудниками, 10 командами, 500 заданиями и 1500 операциями для сортировки, это занимает ~ 7000 мс. Это сравнение, вероятно, было очевидным, но суть в том, что мне нужно найти способ, если возможно, оптимизировать запрос. Я хотел бы приблизить время загрузки к 1 секунде, если это возможно.
Как всегда, спасибо за любую помощь!
Редактировать
Боюсь, я не получаю ответы, на которые надеялся, потому что Я на самом деле не ищу совет по вопросу доступа к данным, я ищу совет по LINQ стороне вопроса. Я не знаю, поможет ли это понять сценарий доступа к данным, поэтому я кратко объясню.
Я кодирую в Xamarin.Forms, используя Autofa c в качестве моего инжектора зависимости. Я пытаюсь использовать интерфейсы, чтобы позволить вызовам к службе данных быть абстрагированными от службы данных.
Данные хранятся на сервере SQL на сервере здесь, в офисе. Приложение использует API для SQL для SQLite под названием Zumero . Zumero синхронизирует запрошенные таблицы с сервера SQL и помещает их в локальный файл на мобильном устройстве.
Я использую Entity Framework Core для передачи данных в программу, снова используя интерфейсы и отображение полей, чтобы попытаться абстрагировать вызовы для объектов базы данных отдельно от самих объектов базы данных. .
Редактировать 2
Я попытаюсь повторить здесь вопрос, чтобы было более понятно, что я ищу:
У меня есть файл SQLite, в котором содержатся сотрудники, операции, ежедневные расписания сотрудников и ежедневные графики работы. Какими способами я мог бы написать запрос, чтобы получить список операций сотрудника, для которых он запланирован?
Воображаемый вопрос:
Что такое запланированные на данный момент операции Боба?
Воображаемые строки в таблицах данных:
Сотрудники
- Боб
- Джим
- Ларри
График работы сотрудников
- Боб 1/1/2020 Бетон Экипаж 1
- Боб 1/2/2020 Бетонная бригада 1
- Боб 1/3/2020 Мельничная бригада 2
Графики работы
- Экипаж 1 1/1/2020 Бетонная операция 1
- Экипаж 2 1/1/2020 Мельница Операция 1
- Экипаж 1 1/2/2020 Бетонная операция 1
- Экипаж 1 1/3/2020 Бетонная операция 3
Операции
- Бетонная операция 1
- Работа на мельнице 1
- Конкретная операция 3
Желаемый результат:
Боб в настоящее время выполняет следующие операции по расписанию: Конкретная операция 1
Это вопрос реляционной базы данных, потому что я аски ng о лучшем способе выяснить связь между сотрудниками с помощью графиков сотрудников и графиков операций.
Спасибо за любую помощь!