Version Example
- Last UpdatedJan 12, 2026
- 6 minute read
- PI System
- AF SDK 3.2.0
- Developer
The following example demonstrates creating a hierarchy of elements, adding new versions of the elements, and then accessing those versions using different approaches.
1// local function to display an error message in the console 2static void ShowError(string message, string title) 3{ 4 ConsoleColor originalColor = Console.ForegroundColor; 5 Console.ForegroundColor = ConsoleColor.Red; 6 7 Console.WriteLine($"{title} --- {message}"); 8 9 Console.ForegroundColor = originalColor; 10} 11 12// Get the Database 13PISystems myPISystems = new PISystems(); 14AFDatabase myDB = myPISystems.DefaultPISystem.Databases.DefaultDatabase; 15 16// Create an Element Template 17AFElementTemplate myElemTemplate = myDB.ElementTemplates.Add("MyElementTemplate"); 18myElemTemplate.Description = "Template used to create my elements"; 19myElemTemplate.CheckIn(); 20 21// Create effective dates 22AFTime baseTime = new AFTime(new DateTime(1995, 6, 30)); 23AFTime time1 = new AFTime(baseTime.UtcTime.AddDays(1)); // Call this T=1 24AFTime time5 = new AFTime(baseTime.UtcTime.AddDays(5)); // Call this T=5 25AFTime time10 = new AFTime(baseTime.UtcTime.AddDays(10)); // Call this T=10 26AFTime time15 = new AFTime(baseTime.UtcTime.AddDays(15)); // Call this T=15 27AFTime time20 = new AFTime(baseTime.UtcTime.AddDays(20)); // Call this T=20 28 29// Create a parent Element with an effective date of T=1 30AFElement parent1 = myDB.Elements.Add("myParent", myElemTemplate, time1); 31parent1.Description = "Parent Element"; 32parent1.CheckIn(); 33 34// Create a second version of the parent Element with an effective date of T=10. 35// Since the first version of the parent is no longer valid for the query date, 36// the first version of the parent will be marked as deleted. Thus, get the 37// first version of the parent again. 38AFElement parent10 = parent1.Version.Create(time10, "T=10") as AFElement; 39parent1 = parent10.ApplyQueryDate(time10.UtcTime.AddDays(-1)) as AFElement; 40 41// Neither version of the parent Element has a child at this point 42// Add a child Element to parent1 with an effective date of T=5. 43AFElement child5 = parent1.Elements.Add("myChildElement", myElemTemplate, time5); 44child5.CheckIn(); 45parent1.CheckIn(); 46 47// Add a second version to child5 with an effective date of T=15. 48AFElement child15 = child5.Version.Create(time15, "T=15") as AFElement; 49 50// Even though child15 was added to the first version of parent1, it won't 51// show up in the child collection of that parent unless the QueryDate of 52// the parent is set to a value of T=5-9. The reason it won't show up 53// before T=5 is that the child element didn't exist before T=5. The 54// reason it won't show up if T>=10 is that the server will use the second 55// version (with an effective date of T=10) to see who the children of 56// 'myParent' are. 57AFElement searchParent; 58searchParent = parent1.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(4))) as AFElement; // T=4 59if (searchParent.Elements.Count > 0) 60 ShowError("Expected 0 sub-elements", "ERROR1"); 61 62searchParent = parent1.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(9))) as AFElement; // T=9 63if (searchParent.Elements.Count != 1) 64 ShowError("Expected 1 sub-elements", "ERROR2"); 65 66searchParent = parent1.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(11))) as AFElement; // T=11 67if (searchParent.Elements.Count > 0) 68 ShowError("Expected 0 sub-elements", "ERROR3"); 69 70// Now add a different element to the second version (T=10) of the parent element. 71AFElement friend15 = parent10.Elements.Add("myFriendElement", myElemTemplate, time15); 72friend15.Description = "Friend Element"; 73friend15.CheckIn(); 74parent10.CheckIn(); 75 76// Add a second version to the friend element. 77// NOTE: It doesn't matter what order we add the versions. 78AFElement friend5 = friend15.Version.Create(time5, "Friend at T=5") as AFElement; 79 80// Now when we set the QueryDate of a copy of parent1 to T=10, we will 81// get the T=5 version of myFriendElement. This shows how it doesn't 82// matter which version of the parent you have. The QueryDate is used 83// to determine which versions to use to get the children. 84searchParent = parent1.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(11))) as AFElement; // T=11 85AFElement searchItem = searchParent.Elements[0]; 86if (searchItem.UniqueID != friend5.UniqueID) // Make sure we got the right element. 87 ShowError("Retrieved wrong element", "ERROR4"); 88 89if (searchItem.Version.EffectiveDate != time5) // Make sure we got the right version. 90 ShowError("Retrieved wrong version", "ERROR5"); 91 92// Now set the QueryDate to null (which represents the current time). This 93// will return the T=15 version for myFriendElement. 94searchParent = parent1.ApplyQueryDate(null) as AFElement; 95searchItem = searchParent.Elements[0]; 96if (searchItem.UniqueID != friend5.UniqueID) // Make sure we got the right element. 97 ShowError("Retrieved wrong element", "ERROR6"); 98 99if (searchItem.Version.EffectiveDate != time15) // Make sure we got the right version. 100 ShowError("Retrieved wrong version", "ERROR7"); 101 102// Now show we can get the children of the parent element with an effective 103// date of T=1. Set the QueryDate to anything between 5-9 and we will get 104// myChildElement. 105searchParent = parent1.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(7))) as AFElement; // T=7 106searchItem = searchParent.Elements[0]; 107if (searchItem.UniqueID != child5.UniqueID) // Make sure we got the right element. 108 ShowError("Retrieved wrong element", "ERROR8"); 109 110if (searchItem.Version.EffectiveDate != time5) // Make sure we got the right version. 111 ShowError("Retrieved wrong version", "ERROR9"); 112 113// NOTE: There is no way to get the T=15 value of myChildElement from the Elements 114// collection of myParentElement because by the time that version is in effect, the 115// parent element has a different child (i.e. myFriendElement). Once you have a 116// version for myChildElement, you can navigate to other versions using the 117// child5.Version.NextVersion, etc. methods. 118 119// The last thing we need to do is to add some grandchildren elements with 120// an effective date of T=20 to the first value of child element (T=5). 121// The second value of child element (T=15) doesn't have this child. 122AFElement grandChild20 = child5.Elements.Add("myGrandChildElement", myElemTemplate, time20); 123grandChild20.CheckIn(); 124child5.CheckIn(); 125 126// Show how it is impossible to find the grandchild element using SetQueryDate 127// and the Elements collection. This is because grandChild20 has a single 128// value with an effective date of T=20. The value of its parent that has an 129// effective date at or before that time is child15 which doesn't have 130// grandChild as a child element. 131searchParent = child5.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(14))) as AFElement; // T=14 132if (searchParent.Elements.Count > 0) 133 ShowError("Expected 0 sub-elements", "ERROR10"); 134 135searchParent = child5.ApplyQueryDate(new AFTime(baseTime.UtcTime.AddDays(25))) as AFElement; // T=25 136if (searchParent.Elements.Count > 0) 137 ShowError("Expected 0 sub-elements", "ERROR11"); 138 139// The only way to find the reference to grandchild element in the first value of 140// the child element is to use the Version.Children collection. This returns a 141// collection of the elements that are referenced by the owner element without 142// using a query date. 143int totalCount; 144IList children = child5.Version.GetChildren(AFSortField.Name, AFSortOrder.Ascending, 0, 10, out totalCount); 145if (children.Count != 1) 146 ShowError("Expected 1 child", "ERROR12"); 147 148searchItem = children[0] as AFElement; 149if (searchItem.UniqueID != grandChild20.UniqueID) // Make sure we got the right element. 150 ShowError("Retrieved wrong element", "ERROR13"); 151 152if (searchItem.Version.EffectiveDate != time20) // Make sure we got the right version. 153 ShowError("Retrieved wrong version", "ERROR14");