Getting and Working With Type Projections - Basic

Getting and Working With Type Projections - Basic

  • Comments 1

In my last post in gave you a more in-depth look at creating type projections in Service Manager. In this post, I'd like to provide you with some basic examples on how you can retrieve and work with instances of type projections. I'll be using the same Management Pack and data set from the previous post.

On the Instances interface you will find a few methods for retrieving instances of EnterpriseManagementObjectProjection. Post Beta 1, we've actually cleaned up this interface significantly so I don't want to concentrate too much on the actual method call, but rather the parameters to it and working with the result.

In Beta 1 the method you would use looks like this:

IList<EnterpriseManagementObjectProjection> GetObjectProjections<T>(ManagementPackTypeProjection managementPackTypeProjection, 
ObjectProjectionCriteria criteria, ObjectQueryOptions queryOptions) where T : EnterpriseManagementObject;

Post Beta 1, this method is replaced by:

IObjectProjectionReader<T> GetObjectProjectionReader<T>(ObjectProjectionCriteria criteria, ObjectQueryOptions queryOptions)
            where T : EnterpriseManagementObject;

The ManagementPackTypeProjection from the first simply gets rolled into the ObjectProjectionCriteria object and the return type gets changed to support buffered reads to help with performance, however, IObjectProjectionReader can actually be used like an IList (although it doesn't implement IList); I'll discuss the reader more once we ship Beta 2 later this year. My examples below will use the latest code since that will be around longer; hopefully it is easily transferable for you to the Beta 1 API.

The first thing you need in order to get a type projection instance, is the type projection definition. This narrows down the types of instances you will get back to those that fit the structure of the type projection:

      // Connect to the management group
      EnterpriseManagementGroup managementGroup =
            new EnterpriseManagementGroup("localhost");

      // Get the management pack
      ManagementPack nflManagementPack = 
            managementGroup.ManagementPacks.GetManagementPack("NFL", null, new Version("1.0.0.0"));

      // Get the type projection
      ManagementPackTypeProjection nflProjection =
            nflManagementPack.GetTypeProjection("NFL.Conference.All");

Very simply you can retrieve projections by specifying the type:

IObjectProjectionReader<EnterpriseManagementObject> objectProjections =
      managementGroup.Instances.GetObjectProjectionReader<EnterpriseManagementObject>(
      new ObjectProjectionCriteria(nflProjection), ObjectQueryOptions.Default);

This will retrieve all projections in the system of that structure. A projection exists if the root object of the projection exists, regardless of whether any of the components are found. If you want to limit your result somehow, you will need to specify criteria to limit your result set. One example of simple criteria you could add is matching on one of the generic properties of the root object:

            string displayNameCriteria = @"<Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
                  <Expression>
                    <SimpleExpression>
                      <ValueExpressionLeft>
                        <GenericProperty>DisplayName</GenericProperty>
                      </ValueExpressionLeft>
                      <Operator>Equal</Operator>
                      <ValueExpressionRight>
                        <Value>National Football Conference</Value>
                      </ValueExpressionRight>
                    </SimpleExpression>
                  </Expression>
                </Criteria>";

            IObjectProjectionReader<EnterpriseManagementObject> objectProjectionsByDisplayName =
                 managementGroup.Instances.GetObjectProjectionReader<EnterpriseManagementObject>(
                     new ObjectProjectionCriteria(displayNameCriteria, nflProjection, managementGroup), ObjectQueryOptions.Default);

This would limit the results to any projections whose root object had a display name matching "National Football Conference." The list of available generic properties for Service Manager is Id, Name, DisplayName, LastModified and new post Beta 1 CreatedDate and LastModifiedBy.

It is also possible to query on type specific properties of the root object:

            string propertyCriteria = @"<Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
                  <Expression>
                    <SimpleExpression>
                      <ValueExpressionLeft>
                        <Property>$Target/Property[Type='NFL.Conference']/Name$</Property>
                      </ValueExpressionLeft>
                      <Operator>Equal</Operator>
                      <ValueExpressionRight>
                        <Value>NFC</Value>
                      </ValueExpressionRight>
                    </SimpleExpression>
                  </Expression>
                </Criteria>";

            IObjectProjectionReader<EnterpriseManagementObject> objectProjectionsByProperty =
                 managementGroup.Instances.GetObjectProjectionReader<EnterpriseManagementObject>(
                     new ObjectProjectionCriteria(propertyCriteria, nflProjection, nflManagementPack, managementGroup), ObjectQueryOptions.Default);

Criteria can get more complicated than the above examples, including specifying criteria on the individual components of the projection, but an in-depth discussion will happen in a later post.

Once you get an EnterpriseManagementObjectProjection, you essentially have a collection of instances organized in a hierarchy as defined by the type projection. If you run the following code:

            foreach (EnterpriseManagementObjectProjection projection in objectProjections)
            {
                Console.WriteLine("Conference: {0}", projection.Object.DisplayName);
                foreach (IComposableProjection division in projection[nflConferenceContainsDivision.Target])
                {
                    Console.WriteLine("\tDivision: {0}", division.Object.DisplayName);
                    foreach (IComposableProjection team in division[divisionContainTeam.Target])
                    {
                        Console.WriteLine("\t\tTeam: {0}", team.Object.DisplayName);
                        foreach (IComposableProjection coach in team[coachCoachesTeam.Source])
                        {
                            Console.WriteLine("\t\t\tCoach: {0}", coach.Object.DisplayName);
                        }
                    }
                }
            }

You'll get a result that shows you the structure of the projection in memory:

Conference: American Football Conference
        Division: AFC West
                Team: Oakland Raiders
                Team: Kansas City Chiefs
                Team: San Diego Chargers
                Team: Denver Broncos
        Division: AFC East
                Team: Buffalo Bills
                Team: New England Patriots
                Team: New York Jets
                Team: Miami Dolphins
        Division: AFC South
                Team: Houston Texans
                Team: Jacksonville Jaguars
                Team: Tennessee Titans
                Team: Indianapolis Colts
        Division: AFC North
                Team: Cleveland Browns
                Team: Pittsburgh Steelers
                Team: Baltimore Ravens
                Team: Cincinnati Bengals
Conference: National Football Conference
        Division: NFC North
                Team: Green Bay Packers
                Team: Chicago Bears
                        Coach: Lovie Smith
                Team: Detroit Lions
                Team: Minnesota Vikings
        Division: NFC South
                Team: Carolina Panthers
                Team: Atlanta Falcons
                Team: Tampa Bay Buccaneers
                Team: New Orleans Saints
        Division: NFC East
                Team: New York Giants
                Team: Dallas Cowboys
                Team: Philadelphia Eagles
                Team: Washington Redskins
        Division: NFC West
                Team: St. Louis Rams
                Team: Seattle Seahawks
                Team: Arizona Cardinals
                Team: San Francisco 49ers

If the line is indented, it indicates a jump across a relationship. The hierarchy is organized by the relationship types that bring in each component; put another way, as you traverse from parent to child you are traversing a relationship of a particular relationship type in one direction. So, as you go from American Football Conference to AFC West, you are moving from "Conference" to "Division" on the NFL.ConferenceHostsDivision relationship type.

Each node in an EnterpriseManagementObjectProjection implements IComposableProjection which offers various ways at traversing through the hierarchy. The object is also IEnumerable<KeyValuePair<ManagementPackRelationshipEndpoint, IComposableProjection>>, which shows that the hierarchy is organized by the relationship endpoint that brings each node in. You also get a pointer to the actual object at the node:

        /// <summary>
        /// The current object in the projection.
        /// </summary>
        EnterpriseManagementObject Object
        {
            get;
        }

The role that brought the current object into the current projection:

        /// <summary>
        /// Gets the role of this projection, relative to its parent.
        /// </summary>
        /// <value></value>
        ManagementPackRelationshipEndpoint ObjectRole
        {
            get;
        }

The object that brought the current object into the current projection:

        /// <summary>
        /// The parent object, if any, for the current object in the projection.
        /// </summary>
        IComposableProjection ParentObject
        {
            get;
        }

And a few indexers to aid in traversal, one of which we used in the sample above:

        /// <summary>
        /// Access all IComposableProjection elements of this IComposableProjection, optionally recursively.
        /// </summary>
        IList<IComposableProjection> this[TraversalDepth traversalDepth]
        {
            get;
        }

        /// <summary>
        /// Access IComposableProjection elements of this IComposableProjection, by role name.
        /// </summary>
        IList<IComposableProjection> this[string roleName]
        {
            get;
        }

        /// <summary>
        /// Access IComposableProjection elements of this IComposableProjection, by role name.
        /// </summary>
        IList<IComposableProjection> this[string roleName, ManagementPackClass classConstraint]
        {
            get;
        }

        /// <summary>
        /// Gets the IComposableProjection child of the projection by id of the contained object
        /// </summary>
        IComposableProjection this[string roleName, Guid id]
        {
            get;
        }

        /// <summary>
        /// Access IComposableProjection elements of this IComposableProjection, by relationship role.
        /// </summary>
        IList<IComposableProjection> this[ManagementPackRelationshipEndpoint role]
        {
            get;
        }

        /// <summary>
        /// Access IComposableProjection elements of this IComposableProjection, by relationship role and a class constraint.
        /// </summary>
        IList<IComposableProjection> this[ManagementPackRelationshipEndpoint role, ManagementPackClass classConstraint]
        {
            get;
        }

        /// <summary>
        /// Gets the IComposableProjection child of the projection by id of the contained object
        /// </summary>
        IComposableProjection this[ManagementPackRelationshipEndpoint role, Guid id]
        {
            get;
        }

In future posts I'll discuss more advanced concepts around working with projections instances (they're IXPathNavigable!), a deeper look at criteria, creating and editing projections and a lot more. I hope that by the time Beta 2 ships later this year to have a comprehensive list of topics that help introduce you to new API concepts.

Leave a Comment
  • Please add 7 and 5 and type the answer here:
  • Post