Having More Fun with Type Projections Using ObjectProjectionCritera
Published Feb 15 2019 08:12 AM 325 Views
First published on TECHNET on Sep 19, 2011

Hopefully everybody is getting up to speed on type projections.  If you haven’t yet had the fun of reading these posts I suggest doing it!


Using the SDK to Create and Edit Objects and Relationships Using Type Projections


Creating Views That Use Related Property Criteria (Type Projections) : Software Views Example ...


Creating a View That Shows Users Which Are Primary Users of Computers Which Have a Certain Soft...


Creating Queues and Groups Using Type Projections


Getting Started with Type Projections


More with Type Projections


Getting and Working With Type Projections – Basic



Now that you are all familiar with type projections and the power that they can provide let’s take a look at a real world customer example!


First, the customer has a concept of a ‘Company’.  Each company has 0..n sites associated with it.  Each site cannot exist without the company parent.  We would model this like this:


<ClassType ID="Company" Accessibility="Public" Abstract="false" Base="System!System.ConfigItem" Hosted="false" Singleton="false" Extension="false">
<Property ID="CompanyID" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" />
<Property ID="Phone" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" />
</ClassType>
<ClassType ID="CompanySite" Accessibility="Public" Abstract="false" Base="System!System.ConfigItem" Hosted="false" Singleton="false" Extension="false">
<Property ID="CompanySiteID" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" />
<Property ID="Phone" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" />
</ClassType>


<RelationshipType ID="Sites" Accessibility="Public" Abstract="false" Base="System!System.Membership">
<Source ID="Source_0f726ba8_caaf_4482_8942_45813659bb23" MinCardinality="0" MaxCardinality="1" Type="Company" />
<Target ID="Target_cefcf9be_8c79_41e4_a8ab_610febb6c1a9" MinCardinality="0" MaxCardinality="2147483647" Type="CompanySite" />
</RelationshipType>


We can then model the company and its member sites using type projections like this:


<TypeProjection ID="CompanyHasMemberSites" Accessibility="Public" Type="Company">
<Component Path="$Target/Path[Relationship='Sites']$" Alias="Site" />
</TypeProjection>


Now, let’s say we want to programmatically create some company, a member site, and then retrieve all the sites for that company!


First the code to create a new company and site:


EnterpriseManagementGroup emg = new EnterpriseManagementGroup("localhost");
ManagementPack mpCompany = emg.ManagementPacks.GetManagementPack("CompanyMP", "9396306c2be7fcc4", new Version(1, 0, 0, 0));
ManagementPackClass classCompany = emg.EntityTypes.GetClass("Company", mpCompany);
ManagementPackClass classCompanySite = emg.EntityTypes.GetClass("CompanySite", mpCompany);
ManagementPackRelationship mprSites = emg.EntityTypes.GetRelationshipClass("Sites", mpCompany);
ManagementPackTypeProjection mptpSites = emg.EntityTypes.GetTypeProjection("CompanyHasMemberSites", mpCompany);


CreatableEnterpriseManagementObject cemoCompany = new CreatableEnterpriseManagementObject(emg, classCompany);
string strCompanyID = Guid.NewGuid().ToString();
Console.WriteLine("New Company ID: " + strCompanyID);
cemoCompany[classCompany, "CompanyID"].Value = strCompanyID;


CreatableEnterpriseManagementObject cemoSite = new CreatableEnterpriseManagementObject(emg, classCompanySite);
string strSiteID = Guid.NewGuid().ToString();
Console.WriteLine("New Site ID: " + strSiteID);
cemoSite[classCompanySite, "CompanySiteID"].Value = strSiteID;


CreatableEnterpriseManagementRelationshipObject cemroCompanySite = new CreatableEnterpriseManagementRelationshipObject(emg, mprSites);
cemroCompanySite.SetSource(cemoCompany);
cemroCompanySite.SetTarget(cemoSite);


IncrementalDiscoveryData idd = new IncrementalDiscoveryData();


idd.Add(cemoCompany);
idd.Add(cemoSite);
idd.Add(cemroCompanySite);


idd.Commit(emg);


This should look pretty straightforward for anyone that has been using the SDK for a while.  First we get the management pack elements like the MP itself, the Company and Site classes, the relationship, and the type projection.


Then we use those to create CreatableEnterpriseManagementObjects for the company and the site.  In this case I am just generating a random GUID as the ID.  We’ll then later use that GUID to look up the Company.


Once we have CreatableEnterpriseManagementObjects in memory and a CreatableEnterpriseManagementRelationshipObject we just need to dump those into a IncrementalDiscoveryData bucket and .Commit() it.


Next, let’s look at how to get a Company (and its member sites) using a type projection and ObjectProjectionCriteria.


First, we need to define the XML criteria string.  This is the tricky bit.


string strCompanySitesByCompanyID = String.Format(@"
<Criteria xmlns="" http://Microsoft.EnterpriseManagement.Core.Criteria/"" >
<Reference Id=""{0}"" Version=""{1}"" PublicKeyToken=""{2}"" Alias=""CompanyMP"" />
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Target/Property[Type='CompanyMP!Company']/CompanyID$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>{3}</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</Criteria>",
mpCompany.Name,
mpCompany.Version.ToString(),
mpCompany.KeyToken,
strCompanyID);


The Reference element at the front simply creates an MP reference to the CompanyMP management pack and sets the alias for that MP to ‘CompanyMP’.  Then we just specify a very simple criteria that says ‘Get all the Company objects (and their member sites) where the CompanyID property = <some passed in value>’.


From there we create an ObjectProjectionCriteria object from the XML string and pass it to GetObjectProjectionReader():


ObjectProjectionCriteria opcCompanySites = new ObjectProjectionCriteria(strCompanySitesByCompanyID, mptpSites, emg);


IObjectProjectionReader<EnterpriseManagementObject> reader = emg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(opcCompanySites, ObjectQueryOptions.Default);



From there we can just loop through the returned Company objects (there will be only one in this case since we are querying by the key property) and the member sites:


foreach (EnterpriseManagementObjectProjection emopCompany in reader)
{
Console.WriteLine("Retrieved Company ID:" + emopCompany.Object.DisplayName);
foreach (IComposableProjection icpSite in emopCompany[mprSites.Target])
{
Console.WriteLine("Site ID: " + icpSite.Object.DisplayName);
}
}


This is what the output of the Program looks like:



Hope that helps!


Source code for the example is attached!


Company-ObjectProjectionCriteria Example.zip

Version history
Last update:
‎Mar 11 2019 08:52 AM
Updated by: