NHibernate 4 Left Outer Join с одним запросом к базе данных
Я новичок в NHibernate, и я использую v4.0.30319, который, кажется, даже не появляется на официальном сайте (я не понимаю, почему?), Поэтому у меня проблемы с поиском хорошей документации.
То, что я хочу, в теории просто. У меня есть 3 таблицы:
- клиент
- ClientAnswer
- Вопрос
Итак, в таблице Вопросы у меня есть вопросы, в Клиентах у меня есть Клиенты и в объединенной таблице ClientAnswer У меня есть ответ Клиента на каждый вопрос (если есть). Возможно, клиент еще не ответил на вопрос, поэтому в ClientAnswer не будет строки.
Я использую FluentNHibernate для отображения, и это выглядит следующим образом:
public ClientMap()
{
Id(x => x.Id);
Map(x => x.Name).Not.Nullable();
Map(x => x.Notes).Nullable();
Map(x => x.IsDeleted).Not.Nullable();
}
public QuestionMap()
{
Id(x => x.Id);
Map(x => x.Description).Not.Nullable();
Map(x => x.IsDeleted).Not.Nullable();
}
public ClientAnswerMap()
{
Id(x => x.Id);
Map(x => x.Value).Not.Nullable();
Map(x => x.IsDeleted).Not.Nullable();
References<Client>(x => x.Client, "ClientId");
References<Driver>(x => x.Question, "QuestionId");
}
Я хотел бы реализовать функцию, которая возвращает список CustomThing, так что каждый CustomThing будет содержать вопрос и ответ этого конкретного клиента (если есть, в противном случае ноль).
IEnumerable<CustomThing> GetQuestionsAndAnswers(int clientId)
быть моим обычным объектом так же просто, как
public class CustomThing
{
public Question Question { get; set; }
public ClientAnswer ClientAnswer { get; set; } //it could be null
}
В SQL я мог бы сделать что-то вроде:
выберите * из Вопроса q оставил внешнее соединение ClientAnswer ca на ca.QuestionId = q.Id
а затем каким-то образом отфильтровать ClientAnswers, ClientId которых не является клиентом, которого я ищу, и поместить результаты в перечисляемый CustomThing. (Надеюсь, я правильно объяснил)
Я открыт для любых предложений, я плохо разбираюсь в SQL:)
Спасибо,
Отредактировано: у меня есть на данный момент это. Но это выглядит очень неэффективно и имеет множественный доступ к базе данных. Но в случае, если это показывает идею того, что я хотел бы иметь:
public IEnumerable<CustomThing> GetQuestionsAndAnswers(int clientId)
{
IList<Question> allQuestions = _session.QueryOver<Question>()
.WhereNot(x => x.IsDeleted).List();
IList<CustomThing> customThings= new List<CustomThing>();
foreach (Question q in allQuestions)
{
CustomThing customThing= new CustomThing();
customThing.Question = q;
customThing.ClientAnswer= GetClientAnswer(clientId, q.Id);
customThings.Add(customThing);
}
return customThings;
}
private ClientAnswer GetClientAnswer(int clientId, int questionId)
{
var clientAnswer = _session.QueryOver<ClientAnswer>()
.Where(x => x.Client.Id == clientId)
.Where(x => x.Question.Id == questionId)
.WhereNot(x => x.IsDeleted).SingleOrDefault();
return clientAnswer; //can be null if the client did not answer this question
}
1 ответ
Если вы добавите Bag в ваш класс Question, ссылающийся на ваш класс ClientAnwsers, вы можете присоединиться к ClientAnwsers в своем запросе allQuestions, как вы делали это в своем SQL-запросе выше.
Поскольку я не использую FluentNHibernate, я не могу показать вам, как именно. Но, может быть, эти три ссылки помогут: