Хотя я много раз пользовался коллективной мудростью этого сайта, это мой первый вопрос здесь.Как вернуть только один конкретный элемент из отношения hasmany
у меня есть, скажем, три класса, как так:
public class ClassA
{
public ClassA() {}
public virtual IList<ClassB> ClassBs { get; set; }
}
public class ClassB
{
public ClassB() {}
public virtual DateTime StartDate { get; set; }
public virtual DateTime? EndDate { get; set; }
public virtual ClassC SomeObject { get; set; }
}
public class ClassC
{
public ClassC() {}
public virtual string Name { get; set; }
}
Я использую NHibernate (3.3.1.4) и FluentNHibernate (1.3.0.733), и файлы отображения являются:
public Class ClassAMap : ClassMap<ClassA>
{
HasMany(x => x.ClassBs);
}
public Class ClassBMap : ClassMap<ClassB>
{
Map(x => x.StartDate).Not.Nullable();
Map(x => x.EndDate).Nullable();
References(x => x.SomeData).Not.Nullable();
}
public Class ClassCMap : ClassMap<ClassC>
{
Map(x => x.Name).Not.Nullable();
}
Есть также идентификаторы и версии, но я почему-то думаю, что они неактуальны.
То, что я хочу сделать, это:
select all "SomeObject"s from ClassBs of all "ClassA"s which have their "EndDate"s null and which have the most current StartDate in their group.
Я пробовал некоторые жонглирование с QueryOver, но максимум, что я мог бы получить был IList<IList<ClassB>>
, который на самом деле далеко от того, что я хочу сделать.
Редактировать: (я думаю) Следующий код выполняет задачу с Linq. Но для этого кода требуются все записи из БД. Это не может быть проблемой для ClassB с до 3-х записей или так для ClassA, но для ClassB с сотнями записей это означает, что все эти записи из БД используют только одну запись из ClassB каждого классаA в БД.
IList<ClassC> classCLs = new List<ClassC>();
ClassB latest = null;
foreach (
IList<ClassB> classBLs in
Session.QueryOver<ClassA>()
.Select(c => c.ClassBs).List<IList<ClassB>>()
) {
latest = classBLs.Where(cB => cB.EndDate == null).Aggregate((curr, next) => next.StartDate > curr.StartDate ? next : curr);
if (latest != null && !classCLs.Contains(latest.SomeObject)) {
classCLs.Add(latest.SomeObject);
}
}
это возвращает объект, состоящий из двух таблиц (ClassA и ClassB), соединенных вместе. Я добавил '.Select (Projections.Property (() => bAlias.SomeObject))' afer строка, начинающаяся с '.WithSubquery ...' и изменившая 'List()' на 'List()' –
mevtagezer
@mevtagezer ok, не понял, что «SomeObject» относится к «SomeObject» класса ClassC и просто читает «Все объекты ClassB» ;-) – jbl
Если вы отредактируете свой ответ, я пометю его как принятый. Спасибо. – mevtagezer