2013-05-14 3 views
0

У меня возникла ситуация, когда я использовал Именованный запрос HQL, но теперь, когда мой DAL изменился, я не знаю, как повторно выполнить именованный запрос в Linq. У меня есть объект, называемый HolterTest, который будет прочитан. Мне нужно создать WorkItem, который будет содержать этот HolterTest, поэтому для этого мне нужно найти все существующие HolterTests, которые еще не имеют WorkItem связанных с ними.Изменение HQL на Linq?

Здесь был мой первоначальный 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> 

Вот мой NHibernate Mapping для WorkItem объекта:

<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> 

Вот файл Mapping для 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(); 
    } 

    } 
} 

Это используется в методе FindAll объекта DAO в:

/// <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(); 
    } 

Вот более простая спецификация, чтобы получить все тесты HolterTest для определенного региона с диапазоном 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 и соединение. Любые предложения/идеи?

UPDATE: Когда я получаю все объекты HolterTest, где RecordingStartDate имеет значение NULL, я могу выполнить цикл и найти те, где WorkItem имеет значение null, но когда я пытаюсь поместить x.WorkItem == null в запросе Spec, я ничего не получил.

ответ

1

Вы дали бы HolterTest свойство коллекции с именем WorkItems и убедитесь, что он не содержит ничего:

x.RecordingStartDate == null && !x.WorkItems.Any() 
+0

Это не совсем работает. Это отношения «один к одному» ... –

+0

Я получаю ответы от компилятора о том, что файл .x.WorkItem недействителен. –

+0

Это очень * редко, что у вас есть отношения один к одному. И если вы действительно сопоставили это как один, то вместо этого был бы «x.WorkItem! = Null». –

Смежные вопросы