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, я не могу показать вам, как именно. Но, может быть, эти три ссылки помогут:

NHibernate Mapping - Набор

Свободное отображение - HasMany / один-ко-многим

NOtherDev: отображение по коду - набор и сумка

Другие вопросы по тегам