我对来自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查询?如果有人在这个领域有任何关于好书或其他学习材料的链接或建议,也会非常有帮助。
答案 0 :(得分:4)
我发现了几个潜在的问题:
我建议使用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();
答案 1 :(得分:0)
将您的查询划分为多个部分并检查哪个部分运行,哪个部分不运行。
我对此的看法是,Linq对nHibernate不支持select new ...
。
我会建议使用别的东西,因为它太过不成熟,而且没有严格使用的功能。
答案 2 :(得分:0)
与大多数流行的LINQ-to-Database查询提供程序一样,NHibernate将尝试将整个查询转换为SQL语句以针对数据库运行。这要求查询的所有元素都可以用您正在使用的SQL风格表达。
在您的查询中,select new
语句无法在SQL中表达,因为您正在调用PatientSearchResultModel
类的构造函数并正在调用GetPhaseTypeModel
方法
您应该重新构建查询以表达要在SQL数据库上执行的内容,然后调用AsEnumerable()
以强制在内存中评估查询的其余部分。在调用之后,您可以调用类的构造函数和任何.NET方法,它们将作为本机代码执行。
答案 3 :(得分:0)
此查询过于复杂,无法使用Linq对其进行描述。它最终会给出错误的结果(如果患者有多个录取记录,结果将有重复的条目)。
我看到了解决方案的两个步骤:
1)在开发阶段,使用内存中查询。所以,先让患者使用ToList()(此时查询db)。在此阶段可以使用一些谓词(像MRN,First,Last这样的患者过滤器)。 然后在内存中搜索。不是性能,而是工作解决方案。将其标记为重构以便稍后进行优化。
2)最后,使用NHibernate IQuery(ISQLQuery)并手动构建sql查询,以确保它能够按预期工作并在SQL Server端运行得足够快。这只是只读查询,根本不需要Nhibernate查询引擎(Linq to Nhibernate)。