2012-06-28 1 views
1

나는 다음과 같은 기관NHibernate에 : 부모를 선택하고 최신 아이

public class Vehicle 
{ 
    public virtual string InternalNumber { get; set; } 
    public virtual IList<VehicleDriverHistory> DriverHistory { get; set; } 
} 

public class VehicleDriverHistory : HistoryEntity 
{ 
    public virtual Vehicle Vehicle { get; set; } 
    public virtual DriverPerson Driver { get; set; } 
    public virtual DateTime Date { get; set; } 
} 

가 지금은 "날짜"에 따라 존재하는 경우, 모든 차량을 선택하고 최신 VehicleDriverHistory-항목이 필요합니다. 하지만 좀 고생하고 있는데, SQL에서 문제가 없지만 지금까지는 nhibernate에서 실패했습니다. 내가 지금까지 무엇을 가지고

:

VehicleDriverHistory vdHistory = null; 
VehicleDriverHistory vdHistory2 = null; 
q.Left.JoinAlias(x => x.DriverHistory,() => vdHistory); 
q.Left.JoinAlias(x => x.DriverHistory,() => vdHistory2).Where(x => vdHistory2.Date > vdHistory.Date); 
q.Where(x => vdHistory2.Id == null); 

이 작동하지 않는 NHibernate에로 (정확한 데이터를 산출) SQL 쿼리를 "번역"그냥 내 시도했다. 그래서

, (없음이 존재하지 않는 경우 또는 없음) 나는 부모와 최신 아이를 선택 얼마나

감사

UPDATE 나는 다음과 결국 Firos의 도움으로

:

VehicleDriverHistory historyAlias = null; 
var maxDateQuery = QueryOver.Of<VehicleDriverHistory>() 
        .Where(h => h.Vehicle == historyAlias.Vehicle) 
        .Select(Projections.Max<VehicleDriverHistory>(h => h.Date)); 

var vehiclesWithEntry = DataSession.Current.QueryOver(() => historyAlias) 
         .WithSubquery.WhereProperty(h => h.Date).Eq(maxDateQuery) 
         .Fetch(h => h.Vehicle).Eager 
         .Future(); 

Vehicle VehicleAlias = null; 
var vehiclesWithoutEntry = DataSession.Current.QueryOver<Vehicle>(() => VehicleAlias) 
          .WithSubquery 
          .WhereNotExists(QueryOver.Of<VehicleDriverHistory>() 
          .Where(x => x.Vehicle.Id == VehicleAlias.Id).Select(x => x.Id)) 
          .Future(); 

return vehiclesWithEntry.Select(h => new PairDTO { Vehicle = h.Vehicle, NewestHistoryEntry = h }).Concat(vehiclesWithoutEntry.Select(v => new PairDTO { Vehicle = v })).ToList(); 

vehulesWithoutEntry의 Any() 문을 하위 쿼리 절로 대체해야했기 때문에 예외가 발생했다.

+0

당신은 당신이 원하는 SQL을 게시 할 수 시도해 볼 수도 있습니다 '최근 날짜'라고 말한 것처럼 질의를 컴파일하는데 도움이되지만'vdHistory2.Date> vdHistory.Date'가 있습니다. – Rippo

+0

번역을 시도한 쿼리입니다. 는' 차량 LEFT OUTER로부터 * 를 선택) vdh2 ON vdh2 그대로 VehicleDriverHistories 가입 vdh1.vdh_vehicleId = vehicles.BVE_Id LEFT OUTER ON vdh1 AS VehicleDriverHistories 가입하세요, 당신은 다른 suggesstion이있는 경우 그러나, 단지 그것을 게시 할 수 있습니다. vdh_vehicleId = 차량 .BVE_Id AND vdh2.vdh_date> vdh1.vdh_date 여기서 vdh2.vdh_vehicleId는 null입니다. ' – Arikael

답변

1

하나의 왕복

VehicleDriverHistory historyAlias = null; 
var maxDateQuery = QueryOver.Of<VehicleDriverHistory>() 
    .Where(h => h.Vehicle == historyAlias.Vehicle) 
    .Select(Projections.Max<VehicleDriverHistory>(h => h.Date)); 

var vehiclesWithEntry = session.QueryOver(() => historyAlias) 
    .WithSubquery.WhereProperty(h => h.Date).Eq(maxDateQuery) 
    .Fetch(h => h.Vehicle).Eager 
    .Select(h => new PairDTO { Vehicle = h.Vehicle, NewestHistoryEntry = h }) 
    .Future<PairDTO>(); 

var vehiclesWithoutEntry = session.QueryOver<Vehicle>() 
    .Where(v => !v.DriverHistory.Any()) 
    .Select(v => new PairDTO{ Vehicle = v }) 
    .Future<PairDTO>(); 

return vehiclesWithoutEntry.Concat(vehiclesWithEntry); // .ToList() if immediate executing is required 

업데이트를 만들기 위해 선물을 사용하여 다른 생각이 의지로, 나는 예외를 재현 할 수 있지만이

VehicleDriverHistory historyAlias = null; 
var maxDateQuery = QueryOver.Of<VehicleDriverHistory>() 
    .Where(h => h.Vehicle == historyAlias.Vehicle) 
    .Select(Projections.Max<VehicleDriverHistory>(h => h.Date)); 

var vehiclesWithEntry = session.QueryOver(() => historyAlias) 
    .WithSubquery.WhereProperty(h => h.Date).Eq(maxDateQuery) 
    .Fetch(h => h.Vehicle).Eager 
    .Future(); 

var vehiclesWithoutEntry = session.QueryOver<Vehicle>() 
    .Where(v => !v.DriverHistory.Any()) 
    .Select(v => new PairDTO{ Vehicle = v }) 
    .Future<PairDTO>(); 

return vehiclesWithoutEntry.Select(h => new PairDTO { Vehicle = h.Vehicle, NewestHistoryEntry = h }).Concat(vehiclesWithEntry); 
+0

귀하의 의견에 감사드립니다. 나는 당신의 샘플을 변형 시켰고 거의 작동합니다. 하지만 concat-method가없는 것 같습니다. 다른 네임 스페이스에 있습니다. 그런 식으로 (의사 코드) '.WithSubquery.WhereProperty (h => h.Date) .Eq (maxDateQuery) .OR (h.Date == NULL)' – Arikael

+0

Concat is 네임 스페이스 System.Linq. .OR (h.Date == NULL)'날짜가 없으면 차량을 없애기위한 기록 레코드가 없기 때문에 작동하지 않습니다? – Firo

+0

흠, 이상한. Concat을 샘플에서 사용하는 방식으로 사용할 수 없습니다. 'vehWithoutEntry.List()'를 호출 한 후에 만 ​​사용할 수 있습니다 – Arikael