来自已查询实体的部分

Posted

技术标签:

【中文标题】来自已查询实体的部分【英文标题】:Sections from already queried Entity 【发布时间】:2011-09-04 21:37:01 【问题描述】:

所以我在 UITableView 中显示一些实体。通过单击单元格,我想显示已经在“对多”关系中查询的其他实体。

例如,我正在显示一所学校的所有班级。现在我想显示一个班级的所有学生。这个学生已经可以作为NSSetClass.students下的Class.students使用

现在我想在不同的部分显示学生的第一个字母。

如果我想直接从 CoreData 获取它们,我会做类似的事情

// init fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:self.managedObjectContext];

// Search only specific students
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"class == %@", theClassThoseStudentsBelongTo];
[fetchRequest setPredicate:predicate];

// Generate it
NSFetchedResultsController *theFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                        managedObjectContext:self.managedObjectContext 
                                          sectionNameKeyPath:@"firstLetter" 
                                                   cacheName:@"StudentTable"];

使用这种方法,我可以将它们很好地排列成部分。

但我已经拥有特定班级的所有学生。有没有办法用初始化的NSSet 初始化NSFetchedResultsController 或做一些相同的事情?

当然,我可以手动安排我的 NSSet,但没有像新查询那样的好方法吗?

提前致谢。 如果有不清楚的地方,请发表评论。

【问题讨论】:

对答案感到好奇,因为我很久以前就遇到过同样的问题,并采取了手动实现所有事情的艰难道路(不难但不方便且不优雅)。 您是希望在单个 tableview 中完成所有这些工作,还是使用 Class-->>class.students 设置分层 tableview? 我有一个带有“classes”的tableview,然后在点击一个类后,一个带有“students”的tableview。 在第一个tableView中使用“学生”吗? (有类的那个?)因为如果我没记错的话,NSFetchedResultsController 获取的对象一开始是错误的,所以学生关系只有在需要时才会延迟加载。 我以某种方式使用它们。我只想知道是否至少存在一名学生。所以我做if (aClass.students) 所以我认为它会查询所有延迟加载的学生,对吗? 【参考方案1】:

我猜你只有两个选择:使用NSFetchedResultsController 或自行排序对象。

NSFetchedResultsController 和 NSPredicate: 优点:容易删除对象;模型更改通知,例如同步期间 缺点:不必要的重新获取

NSSet 和 NSSortDescriptor 优点:无需重新获取 缺点:删除复杂;没有模型更改通知,例如在同步期间:您可能正在显示已被删除的学生

【讨论】:

【参考方案2】:

您可以使用使用反向关系的 NSPredicate(从您的学生回到班级)

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
...

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"class == %@", theClassThoseStudentsBelongTo];
[fetchRequest setPredicate:predicate];

NSFetchedResultsController *theFetchedResultsController = ...

【讨论】:

但这不是再次从sqlite数据库查询学生吗? 很可能是这样。您可以选择使用更多查询的 NSFetchedResultsController 或手动按部分排列对象。【参考方案3】:

NSFetchedResultsController 获取的对象的关系一开始是错误的,并且仅在需要时才获取。这意味着如果我们不为第一个 tableView 使用“Student”实体,它将仅在我们需要时才延迟加载。

但是,由于您需要知道学生人数,因此情况有点复杂,因为调用 [class.students count] 会触发错误。 (调用 KVO @count 也会触发错误)。

所以你有两个选择:

    在班级中管理了一个名为 studentsCount 的属性,该属性反映了学生中的实体数量。调用此属性不会触发关系错误。

    使用 countForFetchRequest:

    NSFetchRequest *req = [[NSFetchRequest alloc] init];
    [req setEntity:[NSEntityDescription entityForName:@"Student" inManagedObjectContext:context]];
    [req setPredicate:[NSPredicate predicateWithFormat:@"class = %@", myClass]];
    

第二个选项执行提取,但效率非常高,所以也许它足够有效 - 我没有进行性能测试,所以我不能说。

顺便说一句,如果您不确定关系是否触发了错误,您可以使用方法 hasFaultForRelationshipNamed。

【讨论】:

以上是关于来自已查询实体的部分的主要内容,如果未能解决你的问题,请参考以下文章

Linq多表查询 返回组合实体 踩坑记

再次查询同一实体

如何编写基于作为父实体spring数据jpa的一部分的字段对结果进行排序的查询方法

递归算法应用——实体树过滤解析

按日期部分比较实体框架中的SQL日期时间

是否有 JPA / JPQL 查询来搜索春季作为 JSON 传递的实体子集?