我有一种情况,我使用的是命名 HQL 查询,但现在我的 DAL 已更改,我不知道如何在 Linq 中重新执行命名查询。我有一个名为 HolterTest 的实体,它将被读入。我需要创建一个包含该 HolterTest 的 WorkItem,所以为了做到这一点,我需要找到所有现有的 HolterTests 还没有 WorkItem与他们相关联。
这是我原来的 HQL 命名查询:
<query name="Get.HolterTests.Without.WorkItems" >
<![CDATA[ from HolterTest as ht
where not exists (from WorkItem as wi
where wi.HolterTest.ID = ht.ID)
and ht.RecordingStartDateTime == null]]>
</query>
这是我的 WorkItem 实体的 NHibernate 映射:
<class name="WorkItem" table="WorkItems" where="" dynamic-update="true" dynamic-insert="true" >
<id name="ID" column="WorkItemID" type="Int32" >
<generator class="identity"/>
</id>
<property name="Status" type="AnsiString" />
<property name="IsCompleted" />
<property name="IsStarted" />
<property name="CompletedDateTime" type="DateTime" />
<many-to-one name="HolterTest" lazy="false" class="HolterTest" column="HolterTestID" unique="true" not-null="true" cascade="save-update"/>
<bag name="WorkTasks" cascade="all-delete-orphan" inverse="true" lazy="false" >
<key column="WorkItemID" on-delete="cascade" />
<one-to-many class="HolterManagementBackend.Domain.Models.WorkTask"/>
</bag>
这是 HolterTest 对象的映射文件,其中我有一对一的映射。
<class name="HolterTest" table="HolterTests" where="" dynamic-update="true" dynamic-insert="true">
<id name="ID" column="HolterTestID" type="Int32" >
<generator class="identity"/>
</id>
<property name="MayoClinicNumber" type="AnsiString" />
<property name="HolterTestType" type="Int32" />
<property name="LastName" type="AnsiString" />
<property name="RecordingStartDate" type="DateTime" not-null="false" />
<property name="HookUpApptDate" type="DateTime" not-null="false" />
<property name="FollowupApptDate" type="DateTime" not-null="false" />
<property name="Room" type="AnsiString" />
<property name="HolterUnitSerial" type="AnsiString" />
<property name="HookupTechLanID" type="AnsiString" />
<property name="OrderingMDLanID" type="AnsiString" />
<property name="ReviewingMDLanID" type="AnsiString" />
<one-to-one name="WorkItem" lazy="false" class="WorkItem" property-ref="HolterTest" cascade="save-update" />
<many-to-one name="Location" class="Location" column="LocationID" not-found="ignore" fetch="join" lazy="false"/>
在我的 DAL 返工中,我现在有了使用 Linq 的抽象类规范:
namespace HolterManagementBackend.DAL.Contracts
{
public abstract class Specification<T>
{
public abstract Expression<Func<T, bool>> MatchingCriteria { get; }
public T SatisfyingElementFrom(IQueryable<T> candidates)
{
return SatisfyingElementsFrom(candidates).Single();
}
public IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates)
{
return candidates.Where(MatchingCriteria).AsQueryable();
}
}
}
这在 DAO 对象的 FindAll 方法中使用:
/// <summary>
/// finds all the objects which match the specification expression provided
/// </summary>
/// <param name="query">the expression to search on</param>
/// <returns>all the objects that match the criteria</returns>
[Transaction( ReadOnly = true)]
public IList<T> FindAll(Specification<T> query)
{
return query.SatisfyingElementsFrom(SessionFactory.GetCurrentSession().Query<T>()).ToList();
}
这是一个更简单的规范,用于获取特定区域的所有 HolterTests,具有 HookupApptDate 范围。
public class GetHolterTestToHookUpByRegionID : Specification<HolterTest>
{
private readonly int _days;
private readonly int _regionId;
public GetHolterTestToHookUpByRegionID(int regionId, int numberOfDays)
{
_days = numberOfDays;
_regionId = regionId;
}
public override Expression<Func<HolterTest, bool>> MatchingCriteria
{
get
{
return x => x.HookUpApptDate <= Convert.ToDateTime(System.DateTime.Today.AddDays(_days))
&& x.Location.Region.ID == _regionId && x.RecordingStartDate == null;
}
}
}
我不知道如何编写包含 NotExists 和连接的规范。有什么建议/想法吗?
更新:通过一对一的方式,当我获得 RecordingStartDate 为空的所有 HolterTest 对象时,我可以循环并找到 WorkItem 为空的对象,但是当我尝试将 x.WorkItem == null 放入查询中时Spec,我什么也拿不回来。