如何使用多对多关系

Posted

技术标签:

【中文标题】如何使用多对多关系【英文标题】:How to use to-many relationship 【发布时间】:2013-08-13 22:14:20 【问题描述】:

假设我有 2 个实体 -- Athlete:with "fullname" 属性 -- Eval:with "pullups" 属性 -- 我想为每个名字设置多个 eval,但是我如何告诉它哪个名字我想将特定的评估添加到?

我的应用与 ios 预装的联系人应用非常相似。根视图控制器有我的第一个实体,运动员。这是一个显示所有运动员的表格视图。当您选择一名运动员时,它会显示他/她的所有信息,并且有一个名为 show eval 的按钮。 Eval 是我的第二个实体。 Athlete 与 Eval 是一对多的关系,这意味着一个运动员可以有多个 eval,但 eval 只能有一个运动员。我知道如何添加评价,但是当我添加它们时,它们就在那里,它们没有所有者,所以无论我选择哪个运动员,它都只会显示所有评价。如何创建与所选运动员相关的评估?

allevals.h

//the athlete selected pushes a tableviewcontroller with all evals, but I want it to only show evals for the athlete selected.
-(void)viewWillAppear:(BOOL)animated
    self.title = [NSString stringWithFormat:@"%@'s Evaluations",_athletesFullName];

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    _managedObjectContext = [appDelegate managedObjectContext];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *eval = [NSEntityDescription entityForName:@"Eval" inManagedObjectContext:_managedObjectContext];
    [request setEntity:eval];
    NSSortDescriptor *sortDescriptor =
    [[NSSortDescriptor alloc] initWithKey:@"date_recorded"
                                ascending:NO
                                 selector:@selector(localizedCaseInsensitiveCompare:)];
    NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];

    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (mutableFetchResults == nil)
        //handle error
    
    [self setEvalArray:mutableFetchResults];
    [self.tableView reloadData];

视图控制器如下,所有运动员的tableview都是根tableviewcontroller,然后有一个add barbuttonitem可以添加运动员。它重新加载视图,然后在 tableview 上你有你新添加的运动员,你点击他,然后它显示细节,加上一个按钮来查看他的 evals。从那里,它是另一个带有 barbuttonitem 的 eval 表视图用于添加。问题是,我不知道如何告诉刚刚添加的 eval 它的所有者是谁。

【问题讨论】:

您何时/何地创建评估?我猜你当时有那个运动员? @Wain 将编辑我的问题。请再检查一遍:-) 【参考方案1】:

添加新评估时: 创建新的评估实体并根据需要设置实体属性。 选择与 eval 一起使用的运动员并调用 addEval: 将两者联系在一起。

当尝试获取运动员的所有评估时,请使用athlete.evals,它只会为您提供附加到相关运动员的评估实体。

【讨论】:

我在 Eval 上设置了“whoTook”关系,但我究竟如何使用 player.evals 进行排序?它不应该像一个 NSPredicate 吗? athlete.evals 将返回一个NSSet 但您可以使用NSSet 方法- (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors 来获得一个按您想要的方式排序的数组。请记住,NSPredicate 用于过滤,NSSortDescriptor 用于排序。 首选哪个?我为什么要使用 NSPredicate 和 NSSortDescriptor? 您使用NSSortDescriptor 获取按日期排序 的评估集合,而您使用NSPredicate 获取来自特定 日期的所有评估, 或 范围 的日期。您还可以将相同的想法应用于实体的任何其他属性。您可以使用 NSPredicate 来查找所有带有 whoTook 且与您正在查看的运动员相匹配的 eval,但由于存在已经拥有该信息的关系,它非常 获取附加到运动员的现有评估集合比查看所有评估并检查运动员是否是正确的更快。 查看速度差异的最简单方法是将 eval 视为在真实纸张上。如果这些纸片已经被运动员叠成一堆,你会只为你想要的运动员寻找那叠纸,还是把所有的 eval 塞进一大堆,然后再寻找具有正确运动员名字的那些?显然,计算机可以比人更快地完成这两件事,但想法是一样的;当工作已经完成时,不要浪费处理器周期和电池电量。【参考方案2】:

您的 fetch 请求有一个 sot 顺序和一个实体描述,但是您错过了它可以处理的第三个项目。

如果您只想过滤适用于运动员的 eval,则需要在 fetchrequest 上设置谓词。

【讨论】:

当我添加一个 eval 时,我需要在那里做任何事情来设置它的所有权吗?或者 Core Data 会为我做这件事吗?例如。在我的评估代码中,我只是插入新实体,我绝不会以任何方式指定运动员。我应该这样做吗? @user2674329,是的,你应该这样做。【参考方案3】:

当用户选择查看运动员的评估时,您需要将该运动员传递给评估视图控制器。视图控制器现在可以在获取要显示的 eval 时在过滤谓词中使用它,并在创建新 eval 时配置对象之间的链接。


newEval.whoTook = self.currentAthlete;

【讨论】:

我理解这个逻辑,但我不明白的是:假设我有 2 个实体 -- 运动员:带有“全名”属性 -- 评估:带有“pullups”属性 - - 我想为每个名称设置多个评估,但我如何告诉它我想将特定评估添加到哪个名称? eval 有 whoTook 关系(就像 whos eval is it),Athlete 有 evals 关系。

以上是关于如何使用多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQLAlchemy 建立多对多关系:一个很好的例子

如何使用 EF6 正确设置多对多关系?

如何使用PowerDesigner软件进行数据库设计(多对多关系)

如何在多对多关系中使用带有可编辑字段的 TabularInline?

如何使用多对多关系

如何使用 Knex.js 查询多对多关系?