public async Task <IActionResult> DoctorsList(int titleId, bool isFirstFree, DateTime date) { var filter = new EntrySearchFilter() { DateTime = date, DepartmentType = DepartmentType.Ambulatory, IsFree = true, IsNearest = isFirstFree, IsDate = !isFirstFree, }; IEnumerable <Entry> doctorsEntries = await _entryDataService.FindDoctor(titleId, filter); return(PartialView("_DoctorsPartial", doctorsEntries)); }
public async Task <IEnumerable <Entry> > FindDoctor(string message, EntrySearchFilter filter) { List <Entry> result = new List <Entry>(); string _string = Regex.Replace(message.Trim(), @"\s+", " "); string[] words = _string.Split(' '); if (_string.Length > 2 || words[0] == "*") { if (words[0] == "*") { words[0] = ""; } using (HospitalDbContext db = _contextFactory.CreateDbContext()) { //Поиск смен по фильтру и строке List <Change> allChanges = await db.Changes .AsQueryable() .OrderBy(c => c.DateTimeStart) .Where(c => c.Staff.Department.Type == filter.DepartmentType) .Where(c => (filter.IsDate ? (c.DateTimeStart.Date == filter.DateTime.Date) : (c.DateTimeStart.Date < (DateTime.Now.AddDays(30))))) .Include(c => c.Staff).ThenInclude(s => s.Department).ThenInclude(d => d.Title) //Далее фильтрация происходит на клиенте, EF не дает добро на обработку сложных запросов сервером(в асинхронном режиме) //StringComparison только на клиенте, если рефакторить на сервер, то через ToLower .AsAsyncEnumerable() .Where(c => ( ((filter.IsName) ? ((words.Any(word => c.Staff.FirstName.Contains(word, StringComparison.CurrentCultureIgnoreCase)) ? 1 : 0) + (words.Any(word => c.Staff.MidName.Contains(word, StringComparison.CurrentCultureIgnoreCase)) ? 1 : 0) + (words.Any(word => c.Staff.LastName.Contains(word, StringComparison.CurrentCultureIgnoreCase)) ? 1 : 0)) : 0) + ((filter.IsQualification) ? (words.Any(word => (c.Staff.Qualification != null) && (c.Staff.Qualification.Contains(word, StringComparison.CurrentCultureIgnoreCase))) ? 1 : 0) : 0) + ((filter.IsDepartment) ? (words.Any(word => (c.Staff.Department.Title.Title != null) && (c.Staff.Department.Title.Title.Contains(word, StringComparison.CurrentCultureIgnoreCase))) ? 1 : 0) : 0) + ((filter.IsAdress) ? (words.Any(word => (c.Staff.Department.Adress.Street != null) && (c.Staff.Department.Adress.Street.Contains(word, StringComparison.CurrentCultureIgnoreCase))) ? 1 : 0) : 0) >= words.Count())) //.Take(50) //подобрать оптимальное значение .ToListAsync(); for (int i = 0; i < allChanges.Count; i++) { Change change = allChanges[i]; //генерация виртуальных записей на текущую смену List <Entry> emptyEntries = new List <Entry>(); foreach (DateTime time in change.GetTimes()) { emptyEntries .Add(new Entry { EntryStatus = Enum.Parse <EntryStatus>("0"), CreateDateTime = DateTime.Now, TargetDateTime = time, DoctorDestination = change.Staff }); } //поиск уже существующих записей на текущую смену !Уходит много времени List <Entry> existEntries = await db.Entries .AsQueryable() .Where(e => e.DoctorDestination.Id == change.Staff.Id) .Where(e => e.TargetDateTime.Date == change.DateTimeStart.Date) .Include(e => e.DoctorDestination).ThenInclude(d => d.Department).ThenInclude(d => d.Title) .ToListAsync(); //объединение записей emptyEntries.AddRange(existEntries); //группировка с заменой совпадений var _result = emptyEntries //.OrderBy(e => e.TargetDateTime) .GroupBy(e => e.TargetDateTime) .Select(e => e.Last()) .Where(e => (filter.IsFree) ? e.EntryStatus == EntryStatus.Открыта : true) .GroupBy(r => r.DoctorDestination.Id) .Select(r => r.First()); //если свободные записи найдены, то все последующие смены этого доктора удаляются из очереди if (filter.IsNearest && _result.Count() != 0) { allChanges.RemoveAll(c => c.Staff.Id == change.Staff.Id && c.DateTimeStart >= change.DateTimeStart); i--; } result.AddRange(_result); } } } return(result); }
public async Task <IEnumerable <Entry> > FindDoctor(int departmentTitleId, EntrySearchFilter filter) { List <Entry> result = new List <Entry>(); using (HospitalDbContext db = _contextFactory.CreateDbContext()) { List <Change> allChanges = await db.Changes .AsQueryable() .OrderBy(c => c.DateTimeStart) .Where(c => c.Staff.Department.Title.Id == departmentTitleId && c.Staff.Department.Type == filter.DepartmentType) .Where(c => filter.IsDate ? (c.DateTimeStart.Date == filter.DateTime.Date) : (c.DateTimeStart.Date < DateTime.Now.AddDays(30))) .Include(c => c.Staff).ThenInclude(s => s.Department).ThenInclude(d => d.Title) //.Take(50) //подобрать оптимальное значение .ToListAsync(); for (int i = 0; i < allChanges.Count; i++) { Change change = allChanges[i]; //генерация виртуальных записей на текущую смену List <Entry> emptyEntries = new List <Entry>(); foreach (DateTime time in change.GetTimes()) { emptyEntries .Add(new Entry { EntryStatus = Enum.Parse <EntryStatus>("0"), CreateDateTime = DateTime.Now, TargetDateTime = time, DoctorDestination = change.Staff }); } //поиск уже существующих записей на текущую смену !Уходит много времени List <Entry> existEntries = await db.Entries .AsQueryable() .Where(e => e.DoctorDestination.Id == change.Staff.Id) .Where(e => e.TargetDateTime.Date == change.DateTimeStart.Date) .Include(e => e.DoctorDestination).ThenInclude(d => d.Department).ThenInclude(d => d.Title) .ToListAsync(); //объединение записей emptyEntries.AddRange(existEntries); //группировка с заменой совпадений var _result = emptyEntries //.OrderBy(e => e.TargetDateTime) .GroupBy(e => e.TargetDateTime) .Select(e => e.Last()) .Where(e => filter.IsFree ? e.EntryStatus == EntryStatus.Открыта : true) .GroupBy(r => r.DoctorDestination.Id) .Select(r => r.First()); //если свободные записи найдены, то все последующие смены этого доктора удаляются из очереди if (filter.IsNearest && _result.Count() != 0) { allChanges.RemoveAll(c => c.Staff.Id == change.Staff.Id && c.DateTimeStart >= change.DateTimeStart); i--; } result.AddRange(_result); } } return(result); }