Linq запрос nhibernate;не поддерживается исключение - PullRequest
1 голос
/ 02 января 2012

Я довольно новичок в nHibernate, пришедший из EF-фона, и я борюсь со следующим запросом:

_patientSearchResultModel = (from patient in _patientRepository.Query(patientSearch.BuildPatientSpecification())
                             join admission in _admissionRepository.Query(patientSearch.BuildAdmissionSpecification())
                                 on patient.Id equals admission.Patient.Id
                             orderby admission.AdmissionDate
                             select new PatientSearchResultModel(patient.Id,
                                 admission.Id,
                                 false,
                               _phaseTypeMapper.GetPhaseTypeModel(admission.PhaseType),
                                 patient.Last, patient.First,
                                 admission.InPatientLocation,
                                 admission.AdmissionDate,
                                 admission.DischargeDate,
                                 admission.RRI,
                                 null,
                                 admission.CompletionStatus,
                                 admission.FollowupStatus)).ToList();

Цель этого запроса - разрешить пользователям фильтровать два запроса по параметрам, построенным с использованием двух функций спецификации Build ???, и возвращать набор результатов. Может быть много записей о поступлении, и я бы хотел, чтобы только один PatientSearchResultModel на каждый объект пациента, при этом объект приема был самым новым к дате поступления.

Эти объекты поступают из nHibernate, и он продолжает возвращать исключение Not Supported. Существует также связь между Patient и Admissions, таким образом: Patient.Admissions, но я не мог понять, как затем добавить фильтры запросов, возвращаемые из функции Build ??? Спецификации.

Я был бы очень благодарен, если бы кто-то мог указать мне правильное направление; Я не согласен с реализацией провайдера Linq здесь, в nHibernate, и мне нужно перейти к критериям или это мой запрос Linq?

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

Ответы [ 4 ]

4 голосов
/ 03 января 2012

Я вижу несколько потенциальных проблем:

  1. Если вы используете NHibernate 2.x + Linq2NHibernate, такие явные объединения не поддерживаются; в других версиях их просто считают запахом.
  2. Я не думаю, что NHibernate поддерживает вызов параметризованных конструкторов в предложениях select
  3. Я уверен, что NHibernate не поддерживает вызов методов экземпляра в лямбде выбора.

Я бы предложил использовать лямбда-синтаксис и SelectMany для устранения потенциальных проблем с объединением. Точки № 2 и № 3 можно решить, спроецировав в анонимный тип, вызвав AsEnumerable , затем спроецировав в тип вашей модели.
В целом, я бы предложил реструктурировать ваш код, например:

var patientSpec = patientSearch.BuildPatientSpecification();
var admissionSpec = patientSearch.BuildAdmissionSpecification();
_patientSearchResultModel = _patientRepository.Where(patientSpec)
    .SelectMany(p=>p.Admissions).Where(admissionSpec)
    .Select(a=> new {
        PatientId = a.Patient.Id,
        AdminssionId = a.Id,
        a.PhaseType,
        a.Patient.Last,
        a.Patient.First,
        a.InPatientLocation,
        a.AdmissionDate,
        a.DischargeDate,
        a.RRI,
        a.CompletionStatus,
        a.FollowupStatus
    }).AsEnumerable()
    .Select(x=> new PatientSearchResultModel(x.PatientId, x.AdmissionId ...))
    .ToList();
0 голосов
/ 07 января 2012

Этот запрос слишком сложен, чтобы описать его с помощью Linq. В конечном итоге это приведет к неверному результату (если у пациента несколько записей о поступлении, в результате появятся повторяющиеся записи).

Я вижу два шага для решения:

1) На этапе разработки используйте запрос в памяти. Итак, сначала возьмите пациентов с помощью ToList () (запросите БД в данный момент). На этом этапе можно использовать некоторые предикаты (фильтр пациента, такой как MRN, первый, последний). А потом заняться поиском в памяти. Не производительность, а рабочее решение. Отметьте это для рефакторинга, чтобы оптимизировать позже.

2) Наконец, используйте NHibernate IQuery (ISQLQuery) и создайте SQL-запрос вручную, чтобы убедиться, что он будет работать должным образом и работать достаточно быстро на стороне SQL Server. Это просто запрос только для чтения, и ему вообще не требуется механизм запросов Nhibernate (от Linq до Nhibernate).

0 голосов
/ 04 января 2012

Как и в большинстве популярных поставщиков запросов LINQ-to-Database, NHibernate попытается преобразовать запрос whole в оператор SQL, который будет работать с базой данных.Для этого необходимо, чтобы все элементы вашего запроса можно было выразить в используемой вами разновидности SQL.

В вашем запросе оператор select new не может быть выражен в SQL, поскольку вы выполняете вызовконструктор вашего класса PatientSearchResultModel и вызывает метод GetPhaseTypeModel.

Вы должны реструктурировать свой запрос, чтобы выразить, что вы хотите выполнить в базе данных SQL, а затем вызвать AsEnumerable(), чтобы принудительноОставшаяся часть запроса будет оценена в памяти.После этого вызова вы можете вызвать конструктор вашего класса и любые методы .NET, и они будут выполнены как собственный код.

0 голосов
/ 02 января 2012

Разделите ваш запрос на части и проверьте, какая часть выполняется, а какая нет.

Я считаю, что select new ... не поддерживается в Linq to nHibernate.

Я бы порекомендовал использовать что-то еще, потому что это просто слишком изящно и бесполезно для серьезного использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...