2010-03-10 1 views
0

У меня есть простая тестовая модель объекта, в которой есть школы, а в школе есть коллекция студентов.nHibernate коллекции и критерии псевдонима

Я хотел бы получить школу и всех ее учеников, которые находятся выше определенного возраста.

Выполняю следующий запрос, который получает данную школу, и дети, которые старше определенного возраста:

public School GetSchoolAndStudentsWithDOBAbove(int schoolid, DateTime dob) 
    { 
     var school = this.Session.CreateCriteria(typeof(School)) 
     .CreateAlias("Students", "students") 
     .Add(Expression.And(Expression.Eq("SchoolId", schoolid), Expression.Gt("students.DOB", dob))) 
     .UniqueResult<School>(); 

     return school; 
    } 

Это все работает отлично, и я могу видеть запрос собирается в базу данных и возвращая ожидаемое количество строк.

Однако, когда я выполняю одно из следующих действий, это дает мне общее количество студентов в данной школе (независимо от предыдущего запроса), запустив еще один запрос:

 foreach (Student st in s.Students) 
     { 
      Console.WriteLine(st.FirstName); 
     } 

     Assert.AreEqual(s.Students.Count, 3); 

Может кто-нибудь объяснить, почему ?

+0

Представляется, что запрос критерии работает 2 запросов. который запускает WHERE (this_.SchoolId = @ p0 и students1_.DateTime> @ p1); @ p0 = '1', @ p1 = '01/01/1997 00:00:00 ' Присоединение к школе и ученику. затем тот, который просто получает необходимую школу – Youeee

ответ

1

К сожалению, s.Students не будет содержать ваши «запрошенные» результаты. Вам нужно будет создать отдельный запрос для учащихся, чтобы достичь своей цели.

foreach(var st in s.Students.Where(x => x.DOB > dob)) 
    Console.WriteLine(st.FirstName); 

Предупреждение: Это все равно будет делать вторую поездку в БД в зависимости от вашего отображения, и он все равно будет получать все студенты.

Я не уверен, но вы могли бы использовать Projections для выполнения всего этого в одном запросе, но я никоим образом не специалист по этому вопросу.

0

У вас есть возможность фильтровать данные. Если это один экземпляр запроса, то выбор mxmissle будет лучшим выбором.

Nhibernate Filter Documentation

Фильтры есть там используются, но в зависимости от версии, которую вы используете могут быть вопросы, где отфильтрованные коллекции не кэшируются правильно.

2

Вы задали свой вопрос по классу школы, и вы ограничили свои результаты на нем, а не на сопоставленных связанных объектах.

Теперь есть много способов сделать это. Вы можете сделать статический фильтр, как сказал IanL, однако его не очень гибкий. Вы можете просто перебирать коллекцию как mxmissile, но это некрасиво и медленно (особенно с учетом ленивых соображений погрузочных)

Я бы обеспечить 2 различные решения: В первом вы поддерживаете запрос у вас есть и вы стреляете динамический фильтр сбор (сохранение ленивой загруженной коллекции) и делать туда-обратно в базу данных:

var school = GetSchoolAndStudentsWithDOBAbove(5, dob); 
IQuery qDob = nhSession.CreateFilter(school.Students, "where DOB > :dob").SetDateTime("dob", dob); 
IList<Student> dobedSchoolStudents = qDob.List<Student>(); 

Во втором растворе просто принести как школы и студент в одном кадре:

object result = nhSession.CreateQuery(
    "select ss, st from School ss, Student st 
    where ss.Id = st.School.Id and ss.Id = :schId and st.DOB > :dob") 
    .SetInt32("schId", 5).SetDateTime("dob", dob).List(); 

ss - объект школы, а st - коллекция учеников.

И это определенно может быть сделано с использованием критериев запроса вы используете сейчас (используя проекции)

 Смежные вопросы

  • Нет связанных вопросов^_^