В одном из моих приложений я пытаюсь добавить информацию о статусе встречи на мой взгляд. Я могу сделать это без особых проблем, и это не сильно замедляет общий запрос - кроме случаев, когда я пытаюсь вычислить один из определенных статусов.
Вот еще один дополнительный фон: статус встречи должен оцениваться путем изучения нескольких полей. По большей части, это не так уж плохо, за исключением тех случаев, когда мне нужно подсчитать, был ли пациент «не явился» на прием.
Чтобы определить неявку, мне нужно взглянуть на поле appt_date
, чтобы увидеть, предшествует ли оно сегодняшней дате. Тем не менее, appt_date сохраняется как VARCHAR
в формате yyyyMMdd
. Чтобы сравнить его с сегодняшней датой, мне нужно преобразовать значение appt_date
в значение Datetime
.
Однако, для этого, мне кажется, мне нужно переключиться с «Linq to Entites» на «Linq to Objects», вызвав AsEnumerable()
в запросе (и внеся некоторые другие незначительные изменения). Конечно, тогда проблема в том, что запрос становится неприемлемо медленным. Насколько я понимаю, подход "Linq to Objects" замедляет работу, поскольку он загружает больше данных в память, поэтому Entity Framework может генерировать правильный запрос SQL.
Есть ли у кого-нибудь какие-либо предложения о том, как мне решить эту проблему и сохранить хорошую производительность с помощью запроса? Буду очень признателен за любые советы, которые вы можете дать.
Для справки, вот запрос с использованием Linq to Entites (и без вычисления «не показывать»):
var referrals =
(from r in _context.Referrals
join cu in _context.ClinicUsers on r.ClinicId equals cu.ClinicId
from ppa in _context.ReferralPPAs
.Where(p => p.ref_id == r.seq_no.ToString())
.DefaultIfEmpty()
from ap in _context.Appointments
.Where(a => a.appt_id.ToString() == ppa.appt_id)
.DefaultIfEmpty()
join ec in _context.EnrolledClinics on r.ClinicId equals ec.ClinicId
join pm in _context.ProviderMasters on ec.ClinicId equals pm.ClinicId
join ml in _context.MasterLists on pm.HealthSystemGuid equals ml.Id
join au in _context.Users on r.ApplicationUserId equals au.Id
where cu.UserId == userId
select new ReferralListViewModel()
{
ClinicName = pm.Description,
ClinicId = r.ClinicId,
ReferralId = r.seq_no,
EnteredBy = (au.FirstName ?? string.Empty) + " " + (au.LastName ?? string.Empty),
PatientName = (r.LastName ?? string.Empty) + ", " + (r.FirstName ?? string.Empty),
DateEntered = r.create_timestamp,
AppointmentDate = ap != null ? ap.appt_date : string.Empty,
AppointmentTime = ap != null ? ap.begintime : string.Empty,
Status = ppa != null ? ppa.Status : string.Empty,
AppointmentStatus = (ap != null & ap.cancel_ind == "N" & ap.confirm_ind == "N" & ap.resched_ind == "N" & ap.appt_kept_ind == "N") ? "Scheduled" :
(ap != null & ap.cancel_ind == "Y") ? "Cancelled" :
(ap != null & ap.confirm_ind == "Y") ? "Confirmed" :
(ap != null & ap.resched_ind == "Y") ? "Rescheduled" :
(ap != null & ap.appt_kept_ind == "Y") ? "Kept" : string.Empty
}).Distinct();
Использование Linq to Objects работает, но недопустимо медленно:
var referrals =
(from r in _context.Referrals
join cu in _context.ClinicUsers on r.ClinicId equals cu.ClinicId
from ppa in _context.ReferralPPAs
.Where(p => p.ref_id == r.seq_no.ToString())
.DefaultIfEmpty()
from ap in _context.Appointments
.Where(a => a.appt_id.ToString() == ppa.appt_id)
.DefaultIfEmpty()
join ec in _context.EnrolledClinics on r.ClinicId equals ec.ClinicId
join pm in _context.ProviderMasters on ec.ClinicId equals pm.ClinicId
join ml in _context.MasterLists on pm.HealthSystemGuid equals ml.Id
join au in _context.Users on r.ApplicationUserId equals au.Id
where cu.UserId == userId
select new { pm.Description, r.ClinicId, r.seq_no, au.FirstName, au.LastName, PatientLastName = r.LastName, PatientFirstName = r.FirstName, r.create_timestamp, ppa.Status, ap.cancel_ind, ap.confirm_ind, ap.resched_ind, ap.appt_kept_ind, ap.appt_date, ap.begintime })
//Calling .AsEnumerable() converts it to Linq to Objects, which allows me to do the date conversion
.AsEnumerable()
.Select(r => new ReferralListViewModel()
{
ClinicName = r.Description,
ClinicId = r.ClinicId,
ReferralId = r.seq_no,
EnteredBy = (r.FirstName ?? string.Empty) + " " + (r.LastName ?? string.Empty),
PatientName = (r.PatientLastName ?? string.Empty) + ", " + (r.PatientFirstName ?? string.Empty),
DateEntered = r.create_timestamp,
Status = r.Status != null ? r.Status : string.Empty,
AppointmentStatus = (r.cancel_ind != null & r.cancel_ind == "N" & r.confirm_ind == "N" & r.resched_ind == "N" & r.appt_kept_ind == "N") ? "Scheduled" :
(r.cancel_ind != null & r.cancel_ind == "Y") ? "Cancelled" :
(r.cancel_ind != null & r.confirm_ind == "Y") ? "Confirmed" :
(r.cancel_ind != null & r.resched_ind == "Y") ? "Rescheduled" :
//Here is the line used to calculate a "no-show" appointment
(r.cancel_ind != null & r.appt_kept_ind == "N" & DateTime.ParseExact(r.appt_date, "yyyyMMdd", CultureInfo.InvariantCulture) < today) ? "No-show" :
(r.cancel_ind != null & r.appt_kept_ind == "Y") ? "Kept" : string.Empty
}).Distinct();