簡體   English   中英

Linq查詢nhibernate; 不支持的例外

[英]Linq query nhibernate; not supported exception

我對來自EF背景的nHibernate相當新,我正在努力解決以下問題:

_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,它會保持返回不支持的異常。 因此,患者和入院之間也存在關聯:Patient.Admissions但我無法弄清楚如何從功能Build ???規范中添加查詢過濾器返回。

如果有人能指出我正確的方向,我真的很感激; 我是否反對nHibernate中的Linq提供程序實現,需要轉移到Criteria還是我的Linq查詢?

如果有人在這個領域有任何關於好書或其他學習材料的鏈接或建議,那也是非常有幫助的。

我看到幾個潛在的問題:

  1. 如果您正在使用NHibernate 2.x + Linq2NHibernate,則不支持這樣的顯式連接; 在其他版本中,它們只是被認為是一種氣味。
  2. 我不認為NHibernate支持在select子句中調用參數化構造函數
  3. 我非常確定NHibernate不支持在select lambda中調用實例方法

我建議使用lambda語法和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();

將您的查詢划分為多個部分,並檢查哪個部分運行,哪個部分不運行。

我對此的看法是Linq對nHibernate不支持select new ...

我會建議使用別的東西,因為它太過不成熟,而且沒有嚴格使用的功能。

與大多數流行的LINQ-to-Database查詢提供程序一樣,NHibernate將嘗試將整個查詢轉換為針對數據庫運行的SQL語句。 這要求查詢的所有元素都可以在您正在使用的SQL風格中表達。

在您的查詢中, select new語句不能用SQL表示,因為您正在調用PatientSearchResultModel類的構造函數並調用GetPhaseTypeModel方法。

您應該重新構建查詢以表達要在SQL數據庫上執行的內容,然后調用AsEnumerable()以強制在內存中計算查詢的其余部分。 在調用之后,您可以調用類的構造函數和任何.NET方法,它們將作為本機代碼執行。

此查詢過於復雜,無法使用Linq進行描述。 它最終會給出錯誤的結果(如果患者有多個錄取記錄,結果將有重復的條目)。

我看到兩個解決方案的步驟:

1)在開發階段,使用內存中查詢。 所以,先讓患者使用ToList()(此時查詢db)。 在此階段可以使用一些謂詞(像MRN,First,Last這樣的患者過濾器)。 然后在內存中搜索。 不是性能,而是工作解決方案。 將其標記為重構以便稍后進行優化。

2)最后,使用NHibernate IQuery(ISQLQuery)並手動構建sql查詢,以確保它能夠按預期工作並在SQL Server端運行得足夠快。 這只是只讀查詢,根本不需要Nhibernate查詢引擎(Linq到Nhibernate)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM