Building a Composition
This guide walks through building a complete Vital Signs Composition containing
blood pressure and heart rate Observation entries, then wrapping it in a Version<T>
and Contribution.
1 — Data type values
// Blood pressure readings
var systolic = new DvQuantity { Magnitude = 120, Units = "mm[Hg]", Precision = 0 };
var diastolic = new DvQuantity { Magnitude = 80, Units = "mm[Hg]", Precision = 0 };
// Heart rate
var heartRate = new DvQuantity { Magnitude = 72, Units = "/min", Precision = 0 };
// Recording time
var now = new DvDateTime(DateTimeOffset.UtcNow.ToString("o"));
2 — Element / ItemTree
var bpTree = new ItemTree
{
Name = new DvText("Tree"),
ArchetypeNodeId = "at0001",
Items = new List<Item>
{
new Element
{
Name = new DvText("Systolic"),
ArchetypeNodeId = "at0004",
Value = systolic
},
new Element
{
Name = new DvText("Diastolic"),
ArchetypeNodeId = "at0005",
Value = diastolic
}
}
};
var hrTree = new ItemTree
{
Name = new DvText("Tree"),
ArchetypeNodeId = "at0001",
Items = new List<Item>
{
new Element
{
Name = new DvText("Rate"),
ArchetypeNodeId = "at0004",
Value = heartRate
}
}
};
3 — Observations
var bpObservation = new Observation
{
Name = new DvText("Blood Pressure"),
ArchetypeNodeId = "openEHR-EHR-OBSERVATION.blood_pressure.v2",
Language = new CodePhrase(new TerminologyId("ISO_639-1"), "en"),
Encoding = new CodePhrase(new TerminologyId("IANA_character-sets"), "UTF-8"),
Subject = new PartySelf(),
Data = new History<ItemStructure>
{
Name = new DvText("History"),
ArchetypeNodeId = "at0001",
Origin = now,
Events = new List<Event<ItemStructure>>
{
new PointEvent<ItemStructure>
{
Name = new DvText("Any event"),
ArchetypeNodeId = "at0006",
Time = now,
Data = bpTree
}
}
}
};
var hrObservation = new Observation
{
Name = new DvText("Heart Rate"),
ArchetypeNodeId = "openEHR-EHR-OBSERVATION.pulse.v2",
Language = new CodePhrase(new TerminologyId("ISO_639-1"), "en"),
Encoding = new CodePhrase(new TerminologyId("IANA_character-sets"), "UTF-8"),
Subject = new PartySelf(),
Data = new History<ItemStructure>
{
Name = new DvText("History"),
ArchetypeNodeId = "at0001",
Origin = now,
Events = new List<Event<ItemStructure>>
{
new PointEvent<ItemStructure>
{
Name = new DvText("Any event"),
ArchetypeNodeId = "at0003",
Time = now,
Data = hrTree
}
}
}
};
4 — Composition
var composition = new Composition
{
Name = new DvText("Vital Signs"),
ArchetypeNodeId = "openEHR-EHR-COMPOSITION.encounter.v1",
ArchetypeDetails = new Archetyped
{
ArchetypeId = new ArchetypeId("openEHR-EHR-COMPOSITION.encounter.v1"),
RmVersion = "1.1.0"
},
Language = new CodePhrase(new TerminologyId("ISO_639-1"), "en"),
Territory = new CodePhrase(new TerminologyId("ISO_3166-1"), "GB"),
Category = new DvCodedText
{
Value = "event",
DefiningCode = new CodePhrase(new TerminologyId("openehr"), "433")
},
Composer = new PartyIdentified { Name = "Dr Alice Smith" },
Context = new EventContext
{
StartTime = now,
Setting = new DvCodedText
{
Value = "primary medical care",
DefiningCode = new CodePhrase(new TerminologyId("openehr"), "228")
}
},
Content = new List<ContentItem> { bpObservation, hrObservation }
};
5 — Version and Contribution
var compositionId = Guid.NewGuid().ToString();
var systemId = "hospital.example.com";
var audit = new AuditDetails
{
SystemId = systemId,
Committer = new PartyIdentified { Name = "Dr Alice Smith" },
TimeCommitted = now,
ChangeType = new DvCodedText
{
Value = "creation",
DefiningCode = new CodePhrase(new TerminologyId("openehr"), "249")
}
};
var version = new OriginalVersion<Composition>
{
Uid = new ObjectVersionId($"{compositionId}::{systemId}::1"),
Data = composition,
LifecycleState = new DvCodedText
{
Value = "complete",
DefiningCode = new CodePhrase(new TerminologyId("openehr"), "532")
},
CommitAudit = audit
};
6 — Validate
var ctx = new ValidationContext(composition);
var results = new List<ValidationResult>();
bool ok = Validator.TryValidateObject(composition, ctx, results, true);
Console.WriteLine(ok ? "Valid" : $"Invalid: {string.Join(", ", results.Select(r => r.ErrorMessage))}");
→ Next: Round-Trip JSON