nHibernate 集合和别名标准

发布于 2024-08-24 09:24:08 字数 795 浏览 3 评论 0原文

我有一个简单的测试对象模型,其中有学校,学校有学生的集合。

我想检索一所学校及其所有超过一定年龄的学生。

我执行以下查询,该查询获取给定的学校和超过一定年龄的儿童:

    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);  

任何人都可以解释为什么吗?

I have a simple test object model in which there are schools, and a school has a collection of students.

I would like to retrieve a school and all its students who are above a certain age.

I carry out the following query, which obtains a given school and the children which are above a certain age:

    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;
    }

This all works fine and I can see the query going to the database and returning the expected number of rows.

However, when I carry out either of the following, it gives me the total number of students in the given school (regardless of the preceding request) by running another query:

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

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

Can anyone explain why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡水深流 2024-08-31 09:24:08

您对 School 类进行了查询,并将结果限制在该类上,而不是映射的相关对象上。

现在有很多方法可以做到这一点。
你可以像 IanL 所说的那样制作一个静态过滤器,但它并不灵活。
您可以像 mxmissile 一样迭代集合,但这既丑陋又缓慢(特别是考虑到延迟加载的考虑因素)

我会提供两种不同的解决方案:
在第一个解决方案中,您维护现有的查询,并对集合触发动态过滤器(维护延迟加载的集合)并往返数据库:

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

在第二个解决方案中,只需在一个解决方案中获取学校和学生shot:

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 是 School 对象,st 是 Student 集合。

这绝对可以使用您现在使用的条件查询来完成(使用投影)

You made your query on the School class and you restricted your results on it, not on the mapped related objects.

Now there are many ways to do this.
You can make a static filter as IanL said, however its not really flexible.
You can just iterate the collection like mxmissile but that is ugly and slow (especially considering lazy loading considerations)

I would provide 2 different solutions:
In the first you maintain the query you have and you fire a dynamic filter on the collection (maintaining a lazy-loaded collection) and doing a round-trip to the database:

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

In the second solution just fetch both the school and the students in one shot:

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 is a School object and st is a Student collection.

And this can definitely be done using the criteria query you use now (using Projections)

时常饿 2024-08-31 09:24:08

不幸的是,s.Students 将不包含您的“查询”结果。您必须为学生创建一个单独的查询才能实现您的目标。

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

警告:根据您的映射,这仍然会第二次访问数据库,并且仍然会检索所有学生。

我不确定,但您可能可以使用投影在一个查询中完成所有这些操作,但我绝不是这方面的专家。

Unfortunately s.Students will not contain your "queried" results. You will have to create a separate query for Students to reach your goal.

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

Warning: That will still make second trip to the db depending on your mapping, and it will still retrieve all students.

I'm not sure but you could possibly use Projections to do all this in one query, but I am by no means an expert on that.

翻了热茶 2024-08-31 09:24:08

您确实可以选择过滤数据。如果有一个查询 mxmissle 选项的实例将是更好的选择。

Nhibernate 过滤器文档

过滤器确实有这些用途,但根据您使用的版本,可能会出现过滤后的集合未正确缓存的问题。

You do have the option of filtering data. If it there is a single instance of the query mxmissle option would be the better choice.

Nhibernate Filter Documentation

Filters do have there uses, but depending on the version you are using there can be issues where filtered collections are not cached correctly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文