Overview of Relationship Types in the System Center Platform

 

The System Center Platform is model based, where classes and their relationships are defined in a management pack. In this blog post I will cover an overview of the four basic relationship types available in the platform.

The inheritance hierarchy of the four relationships is as follows:

Reference Relationship

 

This is the base class of all the relationship types and is the most simple relationship type. It is used as follows in the MP:

        <RelationshipType ID="WorkItemRelatedToConfigItem" Base="System.Reference" Abstract="false" Accessibility="Public">

          <Source ID="WI" Type="WorkItem" />

          <Target ID="CI" Type="System.ConfigItem"/>

        </RelationshipType>

There are no specific rules to be followed while committing instances of this relationship type.

Containment Relationship

 

This relationship is derived from reference relationship. It is used as follows in the MP:

        <RelationshipType ID="QueueContainsWorkItem" Base="System.Containment" Abstract="false" Accessibility="Public">

          <Source ID="Queue" Type="Queue"/>

          <Target ID="WI" Type=" WorkItem"/>

        </RelationshipType>

Properties:

1. Security flows through the contained object. For example, if there are four work items contained in Queue1 and User x has been granted permissions on this queue, then the same user will automatically get permissions to all the work items in that queue.

2. Target class can be used as endpoint of any other relationships types. For example in the example mentioned above, the WorkItem class which is target of the relationship can also be used in other reference or membership relationships too.

There are no specific rules to be followed while committing instances of this relationship type.

Membership Relationship

 

This relationship is derived from containment relationship, so it has the properties of the two relationship types mentioned above. It is used as follows in the MP:

        <RelationshipType ID="WIToTask" Base="System.Membership" Abstract="false" Accessibility="Public">

          <Source ID="WI" Type=" Scenario "/>

          <Target ID="Task" Type="WorkItem"/>

        </RelationshipType>

Properties:

1. Security flows through the contained object (same as containment)

2. Target class can be used as endpoint of other relationships types. (same as containment)

3. The target of this relationship type has a lifetime dependency with the source. In other words, once a membership relationship is established between a source and target, the target’s existence in the system is bound to the source, such that a deletion of the source results in a deletion of the target (but not vice versa).

While committing a membership relationship object you would need to make sure that the target object and the relationship object are committed in the same transaction. Let’s look at an example here

//Create the source object and commit it

      ManagementPackClass classWorkItem = ManagementGroup.EntityTypes.GetClass(“WorkItem”, testMP)

      CreatableEnterpriseManagementObject workItemObject = new CreatableEnterpriseManagementObject(ManagementGroup,classWorkItem);

      workItemObject [classWorkItem, "Id"].Value = Guid.NewGuid().ToString();

      workItemObject [classWorkItem, "Title"].Value = “Hello World”;

      workItemObject.Commit();

      //Create the target object, but since u want to relate this object to the source object and the relationship type is membership do not commit the object

      ManagementPackClass classTask = ManagementGroup.EntityTypes.GetClass(“Task”, testMP)

      CreatableEnterpriseManagementObject taskObject = new CreatableEnterpriseManagementObject(ManagementGroup, classTask);

      taskObject [classTask, "Id"].Value = Guid.NewGuid().ToString();

      taskObject [classTask, "Title"].Value = “Hello World”;

     

      //now create the the relationship object

     CreatableEnterpriseManagementRelationshipObject relationshipObject = new CreatableEnterpriseManagementRelationshipObject(ManagementGroup,

     ManagementGroup.EntityTypes.GetRelationshipClass(“WorkItemToTask”, testMP));

     relationshipObject.SetSource(workItemObject);

     relationshipObject.SetTarget(taskObject);

 

     //since this is a membership relationship type, you would need to commit the target and the relationship object in the same transaction,like follows

     IncrementalDiscoveryData dd = new IncrementalDiscoveryData();

     dd.Add(taskObject); //target object

     dd.Add(relationshipObject); //relationship object

     dd.Commit();

If the membership relationship object is committed without the target object being in the same transaction, then SDK will throw the following exception while committing the relationship

 

DiscoveryDataLifetimeDependencyException - A discovery data item was rejected because the item is already bound to another Membership relationship.

You could insert the target object independent of the relationship object and no sdk error will be thrown. However, if you try to bind this object to a membership relationship later, sdk will throw the same exception as above, since the object was already inserted before the relationship. So for membership relationship it’s very important to have both the target object and relationship object being inserted in the same transaction.

Hosting Relationship

 

This relationship type is derived from the membership relationship type. For using this relationship in the MP, it is required that the target class of this relationship is marked as Hosted=true as shown below:

       <ClassType ID="SQLServerInstance" Accessibility="Public" Base="System.Entity" Hosted="true" Abstract="false">

            <Property ID="SQLId" Type="string" Key="true" />

            <Property ID="Name" Type="string" />

            <Property ID="Comment" Type="string" />

        </ClassType>

        <RelationshipType ID="ComputerToSQLInstance" Base="System.Hosting" Abstract="false" Accessibility="Public">

          <Source ID="Comp" Type="Computer"/>

          <Target ID="SQL" Type=" SQLServerInstance"/>

        </RelationshipType>

Here if you don’t attribute the target class as hosted true, then your MP will fail to import.

 

Properties:

1. Security flows through the contained object (same as containment)

2. The target of this relationship has lifetime dependency with the source (same as membership)

3. Source class of this relationship has to be a non-abstract class

4. Target class shares (partly) the identity of the parent class and hence cannot exist independent of the parent class

5. Target class can belong to one and only one hosted relationship

Hosting relationship is implicitly created when a hosted object is committed; there is no need to explicitly commit a hosting relationship object. For example, if you want to create a SQLServerInstance object related to Computer_XYZ object. Then you would do the following:

 

      ManagementPackClass classComputer = mgmtGrp.EntityTypes.GetClass(“Computer”, sdkTestMP);

ManagementPackClass classSQLServerInstance = mgmtGrp.EntityTypes.GetClass(“SQLServerInstance”, sdkTestMP);

CreatableEnterpriseManagementObject sqlServerObject= new CreatableEnterpriseManagementObject(ManagementGroup, classComputer);

sqlServerObject [classComputer, "Id"].Value = classBObjectId; // here we are setting the key properties of the parent class

sqlServerObject [classSQLServerInstance, " SQLId"].Value = Guid.NewGuid().ToString(); //here we are setting the key properties of hosted class

sqlServerObject.Commit(); //on this commit, the object is commited and implicitly the hosting relationship is also set between the 2 objects

As seen above, you don’t need to explicitly commit a hosting relationship object, as you would need to do for other relationships types.

 

SDK will throw the following exception, if commit is called on a hosted object without the parent key properties filled.

 

System.InvalidOperationException: Either the form is missing some values or the class that created it no longer exists. Make sure all key values are populated and submit again.