У меня есть отношение многие ко многим, которые я пытаюсь запросить. Моя проблема очень похожа на ту, что подробно описал Филипп Хейдон здесь , поэтому я собираюсь свободно позаимствовать его диаграммы и объяснения.
У Филиппа были следующие отношения «многие ко многим» между Джобсом и ролями (извините, я пока не могу вставлять изображения):
схема данных
Филиппу нужно было запросить все роли, которые не были назначены на работу. Его решение было следующим:
Role roleAlias = null;
var existing = QueryOver.Of<JobRole>()
.Where(x => x.Job.JobId == jobId)
.And(x => x.Role.RoleId != roleId)
.And(x => x.Role.RoleId == roleAlias.RoleId)
.Select(x => x.Role);
result = Session.QueryOver<Role>(() => roleAlias)
.Where(x => x.IsEnabled)
.WithSubquery.WhereNotExists(existing)
.OrderBy(x => x.Name).Asc
.List();
Это было очень полезно, однако, похоже, что в этом решении есть сущность для каждой таблицы; Работа, JobRole и Роль. JobRole имеет как работу, так и роль. Вероятно, что-то вроде этого:
public class Job
{
public int JobId {get;set;}
public string Name {get; set;}
public bool IsEnabled {get;set;}
public bool IsDefault {get;set;}
}
public class Role
{
public int RoleId {get;set}
public string Name {get;set}
public bool IsEnabled {get;set}
public string RoleType {get;set}
}
public class JobRole
{
public Job Job {get;set}
public Role Role {get;set;}
}
Это противоречит шаблону, который я видел при моделировании отношений «многие ко многим», особенно в точных примерах архитектуры и из рекомендаций, приведенных здесь. В этих примерах и в моем случае у меня есть только два класса, Job и Role. Примерно так:
public class Job
{
public int JobId {get;set;}
public string Name {get; set;}
public bool IsEnabled {get;set;}
public bool IsDefault {get;set;}
public IList<Role> Roles {get;set;}
}
public class Role
{
public int RoleId {get;set}
public string Name {get;set}
public bool IsEnabled {get;set}
public string RoleType {get;set}
public List<Job> Jobs {get;set;}
}
В моем случае мне нужно найти все рабочие места, которые имеют только роли. Я пробовал что-то вроде этого
Job job = null;
Role role = null;
var jobs = Session.QueryOver(() => job)
.WithSubquery
.WhereExists(
QueryOver.Of(() => role)
.JoinAlias(() => role.Jobs, () => job))
.List().ToList();
но NHibernate требует, чтобы проекция для выбора в WhereExists и жалуется, если он не предоставлен, что имеет смысл для меня.
Можно ли даже с моей моделью выполнить подзапрос QueryOver с WhereExists?
Заранее спасибо.