Key Structure in the Ed-Fi ODS / API

The Ed-Fi ODS / API uses natural keys as its primary means of enforcing uniqueness in records and maintaining relationships between records.

The data in the Ed-Fi ODS / API represents a rich domain with deep relationships. The ODS data store data model is organized into aggregates based on the principles of Domain-Driven Design, and those aggregates are exposed as API resources. Since the ODS is not the system of record (i.e., the system that creates and manages the data), primary keys are formed from the well-known, natural keys in the domain.

The ODS / API also assigns and exposes resource IDs, but those IDs do not act as a surrogate key.

A Natural Key Example Using Bell Schedule Meeting Time

This section provides an example of how this works in practice. Consider the following diagram, noting the composite key structure of BellScheduleMeetingTime:

While SchoolId migrates in from both of the foreign keys from BellSchedule and ClassPeriod, there is only one SchoolId on the BellScheduleMeetingTime. This process of “merging” the SchoolId column from the two keys is known as key unification. In turn, key unification is fundamentally what gives the composite key design approach its power to enforce referential integrity deeply throughout the entire data store — even when data is supplied from many different client systems of record that do not communicate with each other.

When Key Values Change: Cascading Updates

Natural keys are a good solution for the ODS / API because they solve the problem of maintaining referential integrity throughout a deep data structure maintained by client systems that are disconnected from each other. However, natural keys come with an inherent challenge in that a change in a primary key value has the potential to cascade through the primary keys of many child tables. Wherever possible, the ODS / API uses natural keys that are stable and unlikely to change — but change does occur in the real world.

An approach to deal with this challenge is to turn on the CASCADE UPDATE option on all tables and let the database server handle it. Currently, the as-shipped Ed-Fi ODS enables this behavior on selected entities such as Class Period, Grade, Section, and so forth.

The article How To: Enable Cascading Updates on Ed-Fi ODS / API Resources has the full list of entities covered in the as-shipped configuration as well as steps for enabling CASCADE UPDATE on additional entities.

Key Unification Report

Developers and database administrators may find the query in this section of interest.

The query below identifies all locations within the Ed-Fi ODS data store where key unification is occurring. The FOREIGN_TABLE_NAME and FOREIGN_COLUMN_NAME columns represent the tables and columns where key unification is occurring (and consequently, the FOREIGN_COLUMN_NAME values will always appear as identical values in adjacent pairs of records).

WITH ForeignKeys AS
(
-- Key column usage Primary/Foreign tables
SELECT KCU_FK.CONSTRAINT_NAME,
               KCU.TABLE_SCHEMA PRIMARY_TABLE_SCHEMA, 
               KCU.TABLE_NAME PRIMARY_TABLE_NAME, 
               KCU.ORDINAL_POSITION, 
               KCU.COLUMN_NAME PRIMARY_COLUMN_NAME, 
               KCU_FK.TABLE_SCHEMA FOREIGN_TABLE_SCHEMA, 
               KCU_FK.TABLE_NAME FOREIGN_TABLE_NAME, 
               KCU_FK.COLUMN_NAME FOREIGN_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
        JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
               ON KCU.CONSTRAINT_CATALOG=TC.CONSTRAINT_CATALOG
                       AND KCU.CONSTRAINT_SCHEMA=TC.CONSTRAINT_SCHEMA
                       AND KCU.CONSTRAINT_NAME=TC.CONSTRAINT_NAME
        JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
               ON TC.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG
                       AND TC.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA
                       AND TC.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME
        JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU_FK
               ON RC.CONSTRAINT_CATALOG = KCU_FK.CONSTRAINT_CATALOG
                       AND RC.CONSTRAINT_SCHEMA = KCU_FK.CONSTRAINT_SCHEMA
                       AND RC.CONSTRAINT_NAME = KCU_FK.CONSTRAINT_NAME
               AND KCU.ORDINAL_POSITION = KCU_FK.ORDINAL_POSITION
WHERE TC.CONSTRAINT_TYPE='PRIMARY KEY'
    AND KCU.CONSTRAINT_SCHEMA IN ('edfi', 'extension')
    AND KCU_FK.CONSTRAINT_SCHEMA IN ('edfi', 'extension')
),
UnifiedKeyColumns AS
(
SELECT FOREIGN_TABLE_NAME, FOREIGN_COLUMN_NAME, COUNT(*) AS KeyUnificationSources
FROM   ForeignKeys
GROUP BY FOREIGN_TABLE_NAME, FOREIGN_COLUMN_NAME
HAVING COUNT(*) > 1
)
 
SELECT fks.FOREIGN_TABLE_NAME, fks.FOREIGN_COLUMN_NAME, fks.PRIMARY_TABLE_NAME, fks.CONSTRAINT_NAME
FROM   ForeignKeys fks 
               INNER JOIN UnifiedKeyColumns ukc 
                       ON fks.FOREIGN_TABLE_NAME = ukc.FOREIGN_TABLE_NAME
                              AND fks.FOREIGN_COLUMN_NAME = ukc.FOREIGN_COLUMN_NAME
-- Criteria for Section related key unification
ORDER BY FOREIGN_TABLE_NAME, FOREIGN_COLUMN_NAME


Unified Keys in the As-Shipped Ed-Fi ODS

Running the SQL Query above on the as-shipped ODS data store results in the following report:

FOREIGN_TABLE_NAME FOREIGN_COLUMN_NAMEPRIMARY_TABLE_NAMECONSTRAINT_NAME
AcademicWeekSchoolIdCalendarDateFK_AcademicWeek_CalendarDate
AcademicWeekSchoolIdCalendarDateFK_AcademicWeek_CalendarDate1
AcademicWeekSchoolIdSchoolFK_AcademicWeek_School
BellScheduleMeetingTimeSchoolIdBellScheduleFK_BellScheduleMeetingTime_BellSchedule
BellScheduleMeetingTimeSchoolIdClassPeriodFK_BellScheduleMeetingTime_ClassPeriod
CourseOfferingSchoolIdSchoolFK_CourseOffering_School
CourseOfferingSchoolIdSessionFK_CourseOffering_Session
GradeSchoolIdGradingPeriodFK_Grade_GradingPeriod
GradeSchoolIdStudentSectionAssociationFK_Grade_StudentSectionAssociation
GradebookEntrySchoolIdGradingPeriodFK_GradebookEntry_GradingPeriod
GradebookEntrySchoolIdSectionFK_GradebookEntry_Section
ObjectiveAssessmentAssessmentIdentifierAssessmentFK_ObjectiveAssessment_Assessment
ObjectiveAssessmentAssessmentIdentifierObjectiveAssessmentFK_ObjectiveAssessment_ObjectiveAssessment
ObjectiveAssessmentNamespaceAssessmentFK_ObjectiveAssessment_Assessment
ObjectiveAssessmentNamespaceObjectiveAssessmentFK_ObjectiveAssessment_ObjectiveAssessment
ObjectiveAssessmentAssessmentItemAssessmentIdentifierAssessmentItemFK_ObjectiveAssessmentAssessmentItem_AssessmentItem
ObjectiveAssessmentAssessmentItemAssessmentIdentifierObjectiveAssessmentFK_ObjectiveAssessmentAssessmentItem_ObjectiveAssessment
ObjectiveAssessmentAssessmentItemNamespaceAssessmentItemFK_ObjectiveAssessmentAssessmentItem_AssessmentItem
ObjectiveAssessmentAssessmentItemNamespaceObjectiveAssessmentFK_ObjectiveAssessmentAssessmentItem_ObjectiveAssessment
ReportCardGradeGradingPeriodBeginDateGradeFK_ReportCardGrade_Grade
ReportCardGradeGradingPeriodBeginDateReportCardFK_ReportCardGrade_ReportCard
ReportCardGradeGradingPeriodDescriptorIdGradeFK_ReportCardGrade_Grade
ReportCardGradeGradingPeriodDescriptorIdReportCardFK_ReportCardGrade_ReportCard
ReportCardGradeSchoolIdGradeFK_ReportCardGrade_Grade
ReportCardGradeSchoolIdReportCardFK_ReportCardGrade_ReportCard
ReportCardGradeStudentUSIGradeFK_ReportCardGrade_Grade
ReportCardGradeStudentUSIReportCardFK_ReportCardGrade_ReportCard
ReportCardStudentCompetencyObjectiveGradingPeriodBeginDateReportCardFK_ReportCardStudentCompetencyObjective_ReportCard
ReportCardStudentCompetencyObjectiveGradingPeriodBeginDateStudentCompetencyObjectiveFK_ReportCardStudentCompetencyObjective_StudentCompetencyObjective
ReportCardStudentCompetencyObjectiveGradingPeriodDescriptorIdReportCardFK_ReportCardStudentCompetencyObjective_ReportCard
ReportCardStudentCompetencyObjectiveGradingPeriodDescriptorIdStudentCompetencyObjectiveFK_ReportCardStudentCompetencyObjective_StudentCompetencyObjective
ReportCardStudentCompetencyObjectiveSchoolIdReportCardFK_ReportCardStudentCompetencyObjective_ReportCard
ReportCardStudentCompetencyObjectiveSchoolIdStudentCompetencyObjectiveFK_ReportCardStudentCompetencyObjective_StudentCompetencyObjective
ReportCardStudentCompetencyObjectiveStudentUSIReportCardFK_ReportCardStudentCompetencyObjective_ReportCard
ReportCardStudentCompetencyObjectiveStudentUSIStudentCompetencyObjectiveFK_ReportCardStudentCompetencyObjective_StudentCompetencyObjective
ReportCardStudentLearningObjectiveGradingPeriodBeginDateReportCardFK_ReportCardStudentLearningObjective_ReportCard
ReportCardStudentLearningObjectiveGradingPeriodBeginDateStudentLearningObjectiveFK_ReportCardStudentLearningObjective_StudentLearningObjective
ReportCardStudentLearningObjectiveGradingPeriodDescriptorIdReportCardFK_ReportCardStudentLearningObjective_ReportCard
ReportCardStudentLearningObjectiveGradingPeriodDescriptorIdStudentLearningObjectiveFK_ReportCardStudentLearningObjective_StudentLearningObjective
ReportCardStudentLearningObjectiveSchoolIdReportCardFK_ReportCardStudentLearningObjective_ReportCard
ReportCardStudentLearningObjectiveSchoolIdStudentLearningObjectiveFK_ReportCardStudentLearningObjective_StudentLearningObjective
ReportCardStudentLearningObjectiveStudentUSIReportCardFK_ReportCardStudentLearningObjective_ReportCard
ReportCardStudentLearningObjectiveStudentUSIStudentLearningObjectiveFK_ReportCardStudentLearningObjective_StudentLearningObjective
SectionSchoolIdClassPeriodFK_Section_ClassPeriod
SectionSchoolIdCourseOfferingFK_Section_CourseOffering
SectionSchoolIdLocationFK_Section_Location
SectionSchoolIdSchoolFK_Section_School
SectionAttendanceTakenEventSchoolIdCalendarDateFK_SectionAttendanceTakenEvent_CalendarDate
SectionAttendanceTakenEventSchoolIdSectionFK_SectionAttendanceTakenEvent_Section
SessionAcademicWeekSchoolIdAcademicWeekFK_SessionAcademicWeek_AcademicWeek
SessionAcademicWeekSchoolIdSessionFK_SessionAcademicWeek_Session
SessionGradingPeriodSchoolIdGradingPeriodFK_SessionGradingPeriod_GradingPeriod
SessionGradingPeriodSchoolIdSessionFK_SessionGradingPeriod_Session
StaffEducationOrganizationAssignmentAssociationStaffUSIStaffFK_StaffEducationOrganizationAssignmentAssociation_Staff
StaffEducationOrganizationAssignmentAssociationStaffUSIStaffEducationOrganizationEmploymentAssociationFK_StaffEducationOrganizationAssignmentAssociation_StaffEducationOrganizationEmploymentAssociation
StudentAcademicRecordReportCardEducationOrganizationIdReportCardFK_StudentAcademicRecordReportCard_ReportCard
StudentAcademicRecordReportCardEducationOrganizationIdStudentAcademicRecordFK_StudentAcademicRecordReportCard_StudentAcademicRecord
StudentAcademicRecordReportCardStudentUSIReportCardFK_StudentAcademicRecordReportCard_ReportCard
StudentAcademicRecordReportCardStudentUSIStudentAcademicRecordFK_StudentAcademicRecordReportCard_StudentAcademicRecord
StudentAssessmentItemAssessmentIdentifierAssessmentItemFK_StudentAssessmentItem_AssessmentItem
StudentAssessmentItemAssessmentIdentifierStudentAssessmentFK_StudentAssessmentItem_StudentAssessment
StudentAssessmentItemNamespaceAssessmentItemFK_StudentAssessmentItem_AssessmentItem
StudentAssessmentItemNamespaceStudentAssessmentFK_StudentAssessmentItem_StudentAssessment
StudentAssessmentStudentObjectiveAssessmentAssessmentIdentifierObjectiveAssessmentFK_StudentAssessmentStudentObjectiveAssessment_ObjectiveAssessment
StudentAssessmentStudentObjectiveAssessmentAssessmentIdentifierStudentAssessmentFK_StudentAssessmentStudentObjectiveAssessment_StudentAssessment
StudentAssessmentStudentObjectiveAssessmentNamespaceObjectiveAssessmentFK_StudentAssessmentStudentObjectiveAssessment_ObjectiveAssessment
StudentAssessmentStudentObjectiveAssessmentNamespaceStudentAssessmentFK_StudentAssessmentStudentObjectiveAssessment_StudentAssessment
StudentCompetencyObjectiveBeginDateStudentProgramAssociationFK_StudentCompetencyObjective_StudentProgramAssociation
StudentCompetencyObjectiveBeginDateStudentSectionAssociationFK_StudentCompetencyObjective_StudentSectionAssociation
StudentCompetencyObjectiveSchoolIdGradingPeriodFK_StudentCompetencyObjective_GradingPeriod
StudentCompetencyObjectiveSchoolIdStudentSectionAssociationFK_StudentCompetencyObjective_StudentSectionAssociation
StudentCompetencyObjectiveStudentUSIStudentFK_StudentCompetencyObjective_Student
StudentCompetencyObjectiveStudentUSIStudentProgramAssociationFK_StudentCompetencyObjective_StudentProgramAssociation
StudentCompetencyObjectiveStudentUSIStudentSectionAssociationFK_StudentCompetencyObjective_StudentSectionAssociation
StudentGradebookEntryClassPeriodNameGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntryClassPeriodNameStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntryClassroomIdentificationCodeGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntryClassroomIdentificationCodeStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntryLocalCourseCodeGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntryLocalCourseCodeStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntrySchoolIdGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntrySchoolIdStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntrySchoolYearGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntrySchoolYearStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntrySequenceOfCourseGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntrySequenceOfCourseStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntryTermDescriptorIdGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntryTermDescriptorIdStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentGradebookEntryUniqueSectionCodeGradebookEntryFK_StudentGradebookEntry_GradebookEntry
StudentGradebookEntryUniqueSectionCodeStudentSectionAssociationFK_StudentGradebookEntry_StudentSectionAssociation
StudentLearningObjectiveSchoolIdGradingPeriodFK_StudentLearningObjective_GradingPeriod
StudentLearningObjectiveSchoolIdStudentSectionAssociationFK_StudentLearningObjective_StudentSectionAssociation
StudentLearningObjectiveStudentUSIStudentFK_StudentLearningObjective_Student
StudentLearningObjectiveStudentUSIStudentProgramAssociationFK_StudentLearningObjective_StudentProgramAssociation
StudentLearningObjectiveStudentUSIStudentSectionAssociationFK_StudentLearningObjective_StudentSectionAssociation
StudentSchoolAttendanceEventSchoolIdSchoolFK_StudentSchoolAttendanceEvent_School
StudentSchoolAttendanceEventSchoolIdSessionFK_StudentSchoolAttendanceEvent_Session