在多对多关系上添加元素 [英] Adding elements on many-to-many relation

查看:49
本文介绍了在多对多关系上添加元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个项目,您可以从学校的角度计算每个学生的平均水平.您可以在一个屏幕上注册一个学生(第一实体),在另一个屏幕上注册主题(第二实体).学生有姓名,电子邮件,成绩和平均成绩,而科目有姓名.它们彼此之间是多对多的.

我正在尝试为每个学生创建学科列表的副本,然后我可以为每个学生注册每个学科的成绩.像这样:

在此建议的模型中,您可以分配给实体 Enrollment :

的对象
    通过这些属性属性
  • 等级等级(和 date );
  • 通过一个具有 Student 实体的一对多关系属性来
  • 一个学生;
  • 通过与 Subject 实体的一对多关系属性
  • 一个主题.

在以下示例中,我假设核心数据生成了 NSManagedObject 子类-即-在数据模型检查器中,将Codegen的值设置为Class Definition(默认值).

(个人而言,我更愿意为每个实体手动编写 NSManagedObject 子类,并使用 Set 而不是 NSSet ,因为我后来发现在代码中维护类型完整性要容易得多.但是我在这里并没有这样做,因为大多数刚接触Core Data的人都会使用上述Codegen的默认值.)

您可以通过以下方式访问这些值...

 让student = Student()print(学生姓名为:\(String(描述:student.name))")如果让studentEnrolments:NSSet = student.studentEnrolments {用于学生登记中的项目{如果让报名=项目为?注册,让subjectName:字符串= enrolment.subject?.name {print(此学生的主题名称为:\(subjectName)")}}} 

将科目注册分配给学生很容易...

 让enrollment = Enrolment()让subject = Subject()enrollment.subject =主题student.addToStudentEnrolments(入学) 

那么现在或以后,就可以对已注册的科目评分...

  let等级:字符串="A"入学分数=年级 

当然,平均值是根据每个学生的所有年级总和除以计数得出的数学函数.以我的拙见,这是按需的更好构造,而不是与每个 Student 对象一起保存为属性.

更新

我正在更新我的答案,以包括一些数据库理论来解释我提出的对象模型.

根据Wikipedia,数据库规范化是...

构建关系数据库的过程按照一系列所谓的范式减少数据冗余并提高数据完整性.

这对我实际上意味着什么?这意味着将我的数据分解为最离散和唯一的部分,因此从理论上讲,我不需要多次输入任何唯一的数据.

让我使用一个简单的表格示例作为说明,因为它可能会在电子表格(或您的模型概念)中列出:

原始数据

 表1A B C1个学生学科等级2学生1数学8.83学生1物理7.04 Student1 Biology 6.05学生2数学5.06学生2物理9.07学生2生物学7.0 

归一化数据

 表1表2表3A B C A B A B1个学生科目等级ID学生ID科目2 1 1 8.8 1学生1 1数学3 1 2 7.0 2学生2 2物理4 1 3 6.0 3生物学5 2 1 5.06 2 2 9.07 2 3 7.0 

归一化数据在三个表之间使用关系.它存储每个 STUDENT 和每个 SUBJECT ID (作为主键),而不是实际的单词.显然,这可以通过许多不同的方式来提高效率,这些方式包括但不限于:存储数据的字节数,建立索引的能力,数据检索的速度.

当您在Core Data对象模型图中设置 relationship 属性时,您正在做的事情...

因此,在您的示例中,核心数据对象模型图 Entity 代替了TABLE.Core Data框架在构造表时会为我们自动将主键列插入SQLite数据库,然后在以编程方式添加行(记录,实体的实例)时,将主键列自动插入主键唯一整数.作为开发人员,我们没有直接访问权限(使用Core Data),但Core Data框架允许我们建立一对一,一对多和多对多的关系",可以达到相同的结果.

 入学学生科目A B C A B A B相对相对Att.相对Att.相对Att.∞∞1 1Z_PK学生学科等级Z_PK名称Z_PK名称1 1 1 8.8 1学生1 1数学2 1 2 7.0 2学生2 2物理3 1 3 6.0 3生物学4 2 1 5.05 2 2 9.06 2 3 7.0 

Att. =实体 Attribute

Rel. =实体关系

=一对多关系(<< ;-)的许多方面;

1 =一对多关系(->)

的一侧

有什么问题,让我知道吗?

I am making a project where (from the perspective of school) you can calculate each student average. You can register a student (first entity) on a screen and subjects (second entity) on another screen. Student has name, email, grade and average as atributes, and Subjects has name. They relate many-to-many with each other.

I am trying to create a copy of subjects list to each student, then on each student i can register a grade to each subject. Like this:

Model concept

Model: !https://imgur.com/gmXyR5j

I've created a singleton of subjects since it is used more than one location:

import Foundation
import CoreData

class SubjectsManager {
    static let shared = SubjectsManager()
    var subjects: [Subject] = []

    func loadSubject(with context: NSManagedObjectContext) {
        let fetchRequest: NSFetchRequest<Subject> = Subject.fetchRequest()
        let sortDescritor = NSSortDescriptor(key: "name", ascending: true)
        fetchRequest.sortDescriptors = [sortDescritor]

        do {
            subjects = try context.fetch(fetchRequest)
        } catch {
            print(error.localizedDescription)
        }
    }

    func deleteSubject(index: Int, context: NSManagedObjectContext) {
        let subject = subjects[index]
        context.delete(subject)

        do {
            try context.save()
            subjects.remove(at: index)
        } catch {
            print(error.localizedDescription)
        }
    }

    private init() {

    }
}

And, on my student screen, i've tried many thing but nothing is working. The to-many relation of student with subject is called registeredSubjects I've created a NSSET called subjectsManagerSet to get values from the singleton, but it not working. Here what i've tried so far:

subjectManagerSet.addingObjects(from: subjectsManager.subjects)

Also tried to create a for loop of subjectManager.subjects to add on subjectManagerSet but it's not working too.

About errors, when i get samples from xcode output, it keep showing that subjectManagerSet did not get values from subjectManager.subject

Error message:

2019-09-26 20:38:16.983725-0300 MyAverage[1734:62290] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/vitorgomes/Desktop/Mentorizacao/MyAverage/MyAverage/Controllers/StudentsViewController.swift, line 119
(lldb) po subjectManagerSet
0 elements

The expected result is that i want a copy of subjects for each student instance, then i can add grades for each subjects for each student.

解决方案

The expected result is that i want a copy of subjects for each student instance, then i can add grades for each subjects for each student.

I am not addressing your problem as stated at the beginning of your question, but the one stated at the end, per the quote above.

I would encourage you to reconsider the structure of your model.

Perhaps something like this?

In this proposed model, you're able to assign to an object of the entity Enrolment:

  • a grade (and date) via these attribute properties;
  • a student via the one-to-many relationship property with a Student entity;
  • a subject via the one-to-many relationship property with a Subject entity.

In the following examples, I assume Core Data generated NSManagedObject subclasses - that is - in the Data Model Inspector, set the value for Codegen = Class Definition (default).

(Personally and as an aside, I prefer to manually write NSManagedObject subclasses for each of my entities and use Set rather than the NSSet, as I find it subsequently a lot easier to maintain type integrity in my code. But I have not done that here as most people who are new to Core Data will use the default for Codegen noted above.)

You're able to access these values in the following manner...

    let student = Student()

    print("Student name is: \(String(describing: student.name))")

    if let studentEnrolments: NSSet = student.studentEnrolments {

        for item in studentEnrolments {

            if
                let enrolment = item as? Enrolment,
                let subjectName: String = enrolment.subject?.name {

                print("Subject name for this student is: \(subjectName)")
            }
        }
    }

Its easy to assign a subject enrolment to a student...

    let enrolment = Enrolment()
    let subject = Subject()

    enrolment.subject = subject

    student.addToStudentEnrolments(enrolment)

Then now or later, a grade can be applied to the enrolled subject...

    let grade: String = "A"

    enrolment.grade = grade

Of course the average becomes a mathematical function based on the sum of all grades for each student, divided by the count. This is in my humble opinion, better constructed as it is needed, rather than saved as an attribute with each Student object.

Update

Im updating my answer to include a little database theory to explain my proposed object model.

According to Wikipedia, Database normalisation is...

the process of structuring a relational database in accordance with a series of so-called normal forms in order to reduce data redundancy and improve data integrity.

What does this practically mean to me? It means breaking my data down into its most discrete and unique parts, so that, in theory, I never need to enter any unique piece of data more than once.

Let me use a simple table example as a means of explaining this, as it might be set out in a spreadsheet (or your model concept):

Original Data

     TABLE 1
     A          B           C
1    STUDENT    SUBJECT     GRADE    
2    Student1   Mathematics 8.8
3    Student1   Physics     7.0
4    Student1   Biology     6.0
5    Student2   Mathematics 5.0
6    Student2   Physics     9.0
7    Student2   Biology     7.0

Normalised Data

     TABLE 1                             TABLE 2              TABLE 3
     A          B           C            A     B              A     B
1    STUDENT    SUBJECT     GRADE        ID    STUDENT        ID    SUBJECT
2    1          1           8.8          1     Student1       1     Mathematics
3    1          2           7.0          2     Student2       2     Physics
4    1          3           6.0                               3     Biology
5    2          1           5.0
6    2          2           9.0
7    2          3           7.0

The normalised data uses relationships between the three tables. It stores the ID (as a primary key) of each STUDENT and each SUBJECT, instead of the actual words. This is obviously far more efficient in many different ways, including but not limited to: bytes of stored data, ability to index, speed of data retrieval.

When you set a relationship property in your Core Data object model graph, you are doing the same thing...

So for your example, the Core Data object model graph Entity replaces TABLE. The Core Data framework automagically inserts a primary key column into the SQLite database for us when it constructs the tables and later a primary key unique integer when we programmatically add rows (records, a.k.a instances of an entity). While we don't have direct access to that as a developer (using Core Data), the Core Data framework allows us to build one-to-one, one-to-many and many-to-many relationships between two entities, that achieves the same outcome.

     Enrolment                           Student              Subject
     A          B           C            A     B              A     B
     Rel.       Rel.        Att.         Rel.  Att.           Rel.  Att.
     ∞          ∞                        1                    1
Z_PK Student    Subject     grade        Z_PK  name           Z_PK  name
1    1          1           8.8          1     Student1       1     Mathematics
2    1          2           7.0          2     Student2       2     Physics
3    1          3           6.0                               3     Biology
4    2          1           5.0
5    2          2           9.0
6    2          3           7.0

Att. = Entity Attribute;

Rel. = Entity Relationship;

= many side of one-to-many Relationship (<<-);

1 = one side of one-to-many Relationship (-->)


Any questions, let me know?

这篇关于在多对多关系上添加元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆