March, 2009

  • Jakub@Work

    Getting and Working With Type Projections - Basic

    • 1 Comments

    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.

Page 1 of 1 (1 items)