PortfolioAnalyses.CommitOptimizerSolution method

Commits the solution (and the associated projects) to the workflow step, using the unique identifier for the solution.

Namespace:  WebSvcPortfolioAnalyses
Assembly:  ProjectServerServices (in ProjectServerServices.dll)

Syntax

'Declaration
<SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/PortfolioAnalyses/CommitOptimizerSolution", RequestNamespace := "https://schemas.microsoft.com/office/project/server/webservices/PortfolioAnalyses/",  _
    ResponseNamespace := "https://schemas.microsoft.com/office/project/server/webservices/PortfolioAnalyses/",  _
    Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Sub CommitOptimizerSolution ( _
    solutionUid As Guid _
)
'Usage
Dim instance As PortfolioAnalyses
Dim solutionUid As Guid

instance.CommitOptimizerSolution(solutionUid)
[SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/PortfolioAnalyses/CommitOptimizerSolution", RequestNamespace = "https://schemas.microsoft.com/office/project/server/webservices/PortfolioAnalyses/", 
    ResponseNamespace = "https://schemas.microsoft.com/office/project/server/webservices/PortfolioAnalyses/", 
    Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public void CommitOptimizerSolution(
    Guid solutionUid
)

Parameters

Remarks

Project Server Permissions

Permission

Description

ManagePortfolioAnalyses

Allows a user to create portfolio analyses. Global permission.

Examples

The example uses the SvcPortfolioAnalyses namespace in the ProjectServerServices.dll proxy assembly. The ConfigClientEndpoints and the SetClientEndPoints method use an app.config file for setting the WCF binding, behavior, and endpoint. For information about creating a PSI proxy assembly and an app.config file, see Prerequisites for WCF-based code samples in Project 2013.

Note

The following example is designed to illustrate the use of various PortfolioAnalyses methods; it is not a full solution The GUIDs are hardcoded for the necessary local project, drivers, driver prioritization, and so forth. To use the example, change the GUID values to match those in you test installation of Project Server 2013

The complete sample code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ServiceModel;
using PSLibrary = Microsoft.Office.Project.Server.Library;

// The following code requires one project, two drivers and a driver 
// prioritization to exist in the database. Change the values of all hard-coded
// GUIDs to match values in your instance.
// You can make the same logic work for more than one project by 
// adding a FOR -EACH loop.
namespace Microsoft.SDK.Project.Samples.Portfolio
{
    class PortFolio
    {
        private const string PROJECT_GUID = 
            "C13FEAEB-8A19-4F43-BECD-44F43B1A82D9";
        private const string DRIVER0_GUID = 
            "CB75B3E4-4F7A-44A3-BAE1-59061B44B156";
        private const string DRIVER1_GUID = 
            "BC858049-D638-480B-8071-E5EABE995FE8";
        private const string DRIVER_PRIORITIZATION_GUID =
            "9ADF2C29-D409-41EB-BC6C-6B7BFCDC0CAA";
        private const string ALT_PROJECT_STARTDATE_CF_GUID =
             "5B21E11D-0B2F-4D93-8995-F4A6625EB3EB";
        private const string ALT_PROJECT_ENDDATE_CF_GUID =
            "5B21E11D-0B2F-4D93-8995-F4A6625EB3EB";
        private const string HARD_CONSTRAINT_CF_GUID = 
            "DC68B96A-965E-4B25-AC8A-15A5DF729831";
        private const string MD_PROP_GUID = 
            "DC68B96A-965E-4B25-AC8A-15A5DF729831";
        private const string BINARY_USING_CF_PRIORITY_GUID =
             "C834DF36-6712-4891-92B0-FA6BFB5775FD";
        private const string GREATER_THAN_LOOKUPTABLE_VALUE =
            "426F8D32-6961-4B4B-91AB-705F0200F45E";
        private const string LESS_THAN_LOOKUPTABLE_VALUE =
            "779271C4-894D-4385-9E33-1251A9E80541";

        private const string ENDPOINT_PA = "basicHttp_PortfolioAnalyses";
        private const string ENDPOINT_Q = "basicHttp_QueueSystem";
        private const string OUTPUT_FILES = @"C:\Projects\Samples\Output\";
        private static string outFilePathAnalysisDS;
        private static string outFilePathUpdatedAnalysisInfo;
        private static string outFilePathOptimizerDS;

        private static SvcPortfolioAnalyses.PortfolioAnalysesClient analysesClient;
        private static SvcQueueSystem.QueueSystemClient queueSystemClient;
        
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;

            // Configure the end points.
            ConfigClientEndpoints(ENDPOINT_PA);
            SetClientEndpoints(ENDPOINT_Q);

            // If output directory does not exist,create it.
            if (!Directory.Exists(OUTPUT_FILES))
            {
                Directory.CreateDirectory(OUTPUT_FILES);
            }
            outFilePathAnalysisDS = OUTPUT_FILES + "AnalysisDataSet.xml";
            outFilePathUpdatedAnalysisInfo = OUTPUT_FILES + "UpdatedAnalysisInfo.xml";
            outFilePathOptimizerDS = OUTPUT_FILES + "OptimizerSolutionDS.xml";

            // Create the Portfolio Analysis DataSet.
            SvcPortfolioAnalyses.AnalysisDataSet portfolioAnalysisDS =
                new SvcPortfolioAnalyses.AnalysisDataSet();
            Guid analysis_uid;
            Guid[] numDrivers;
            Guid jobGuid;

            // Create analysis.
            CreateAnalysis(portfolioAnalysisDS,
                out analysis_uid,
                out numDrivers,
                out jobGuid);

            // Read analysis.
            SvcPortfolioAnalyses.AnalysisDataSet analysisDSAfterAdd =
                analysesClient.ReadAnalysis(analysis_uid);

            // Write the DataSet contents to an XML file.
            analysisDSAfterAdd.WriteXml(outFilePathAnalysisDS);

            // Update the Portfolio Analysis.
            analysisDSAfterAdd = UpdateAnalysis(analysis_uid,
                numDrivers, jobGuid, analysisDSAfterAdd);

            // Create the Optimizer Solution.
            CreateOptimizerSolution(analysis_uid,
                analysisDSAfterAdd);

        }

        // Creates the Optimizer Solution.
        private static void CreateOptimizerSolution(Guid analysis_uid,
            SvcPortfolioAnalyses.AnalysisDataSet analysisDSAfterAdd)
        {
            // Create the Optimizer Solution DataSet.
            SvcPortfolioAnalyses.OptimizerSolutionDataSet solutionDS =
                new SvcPortfolioAnalyses.OptimizerSolutionDataSet();
            SvcPortfolioAnalyses.OptimizerSolutionDataSet.SolutionRow
                solutionRow =
                solutionDS.Solution.NewSolutionRow();
            Guid solutionGuid = Guid.NewGuid();
            string solutionName = "Baseline";
            solutionRow.ANALYSIS_UID = analysis_uid;
            solutionRow.SOLUTION_UID = solutionGuid;
            solutionRow.SOLUTION_NAME = solutionName;
            solutionRow.OPT_USE_DEPENDENCIES = true;  // The default is true.
            solutionDS.Solution.AddSolutionRow(solutionRow);

            // Populate DecisionsTable with projects and force-in/force-out status
            // and PrioritiesTable with projects and project priority.
            foreach (SvcPortfolioAnalyses.AnalysisDataSet.AnalysisProjectsRow
                projRow in
                analysisDSAfterAdd.AnalysisProjects.Rows)
            {
                SvcPortfolioAnalyses.OptimizerSolutionDataSet.SolutionProjectsRow
                     solutionsProjectsRow =
                     solutionDS.SolutionProjects.NewSolutionProjectsRow();

                solutionsProjectsRow.SOLUTION_UID =
                    solutionDS.Solution[0].SOLUTION_UID;
                solutionsProjectsRow.PROJ_UID = projRow.PROJ_UID;

                // Leave decision to the optimization (Auto = 2).
                solutionsProjectsRow.FORCE_STATUS = (byte)PSLibrary.Optimizer.ForceStatus.Auto;
                solutionDS.SolutionProjects.AddSolutionProjectsRow(
                    solutionsProjectsRow);
            }

            // Populate SolutionConstraintValuesDataTable with custom field 
            // Guid/Value pairs for each project.
            Decimal constraintTotal = 0;
            int num_value = 0;
                        
            SvcPortfolioAnalyses.OptimizerSolutionDataSet.SolutionConstraintsRow
                solutionConstraintsRow =
                solutionDS.SolutionConstraints.NewSolutionConstraintsRow();
            solutionConstraintsRow.SOLUTION_UID =
                solutionDS.Solution[0].SOLUTION_UID;
            solutionConstraintsRow.MD_PROP_UID = new Guid(MD_PROP_GUID);
            solutionConstraintsRow.MD_PROP_POS = 0;
            solutionConstraintsRow.MAX_VALUE = constraintTotal;
            solutionDS.SolutionConstraints.AddSolutionConstraintsRow(
                solutionConstraintsRow);

            foreach (SvcPortfolioAnalyses.AnalysisDataSet.AnalysisProjectsRow
                projRow in
                analysisDSAfterAdd.AnalysisProjects.Rows)
            {
                SvcPortfolioAnalyses.OptimizerSolutionDataSet.
                    SolutionConstraintValuesRow
                    solutionConstraintValuesRow =
                    solutionDS.SolutionConstraintValues.
                    NewSolutionConstraintValuesRow();
                solutionConstraintValuesRow.SOLUTION_UID =
                    solutionDS.Solution[0].SOLUTION_UID;
                solutionConstraintValuesRow.MD_PROP_UID = new Guid(MD_PROP_GUID);
                solutionConstraintValuesRow.PROJ_UID = projRow.PROJ_UID;

                constraintTotal += solutionConstraintValuesRow.NUM_VALUE =
                    Convert.ToDecimal(num_value);
                solutionDS.SolutionConstraintValues.
                    AddSolutionConstraintValuesRow(
                    solutionConstraintValuesRow);
            }
            Guid jobUid = Guid.NewGuid();
            try
            {
                // Create the Optimizer Solution.
                analysesClient.QueueCreateOptimizerSolution(
                    analysis_uid, solutionDS, jobUid);
                Helpers.WaitForQueue(SvcQueueSystem.QueueMsgType.
                    OptimizerSolutionCreate,
                    1, queueSystemClient, jobUid);
                Console.WriteLine("Optimizer solution created successfully.");
            }
            catch (CommunicationException e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(
                    "\n***System.ServiceModel.CommunicationException:");
                Console.WriteLine(e.ToString());
                Console.ResetColor();
            }

            // Read the contents of the Optimizer Solution DataSet.
            SvcPortfolioAnalyses.OptimizerSolutionDataSet
                optimizerSolutionDS =
                analysesClient.ReadOptimizerSolution(solutionGuid);
            optimizerSolutionDS.WriteXml(outFilePathOptimizerDS);

            // Commit Optimizer Solution.
            analysesClient.CommitOptimizerSolution(solutionGuid);
            Console.WriteLine("Optimizer solution committed.");
            Console.Read();
        }

        // Create the Portfolio Analysis.
        private static void CreateAnalysis(
            SvcPortfolioAnalyses.AnalysisDataSet portfolioAnalysisDS,
            out Guid analysis_uid,
            out Guid[] numDrivers,
            out Guid jobGuid)
        {
            string analysisName = "Analysis" + Guid.NewGuid();
            analysis_uid = Guid.NewGuid();
            Guid PROJECT_IMPACT_MD_PROP_UID = 
                new Guid(PSLibrary.CustomField.PROJECT_IMPACT_MD_PROP_UID.ToString());
            Guid RoleCFGuid = 
                new Guid(PSLibrary.CustomField.COST_TYPE_MD_PROP_UID.ToString());
            numDrivers = new Guid[2];
            numDrivers[0] = new Guid(DRIVER0_GUID);
            numDrivers[1] = new Guid(DRIVER1_GUID);

            int prioritizationType = (int)PSLibrary.Optimizer.PrioritizationType.BinaryUsingPrioritization;
            int analysisType = (int)PSLibrary.Optimizer.AnalysisType.Cost_and_Schedule;

            int binaryUsingPrioritizationPrioType =
                (int)PSLibrary.Optimizer.AnalysisType.Cost;
            object impactGuid = null;

            if (prioritizationType == binaryUsingPrioritizationPrioType)
                impactGuid = PROJECT_IMPACT_MD_PROP_UID;

            SvcPortfolioAnalyses.AnalysisDataSet.AnalysisRow analysisRow =
                portfolioAnalysisDS.Analysis.NewAnalysisRow();
            analysisRow.ANALYSIS_NAME = analysisName;
            analysisRow.ANALYSIS_UID = analysis_uid;
            analysisRow.ANALYSIS_TYPE = analysisType;
            analysisRow.PRIORITIZATION_TYPE = prioritizationType;
            analysisRow.PRIORITIZATION_UID = new Guid(DRIVER_PRIORITIZATION_GUID);
            analysisRow.ROLE_CUSTOM_FIELD_UID = RoleCFGuid;
            analysisRow.PROJECT_IMPACT_CF_UID = new Guid(impactGuid.ToString());
            analysisRow.ALT_PROJ_START_DATE_CF_UID = new Guid(ALT_PROJECT_STARTDATE_CF_GUID);
            analysisRow.ALT_PROJ_END_DATE_CF_UID = new Guid(ALT_PROJECT_ENDDATE_CF_GUID);
            analysisRow.HORIZON_START_DATE = new DateTime(2010, 1, 1);
            analysisRow.HORIZON_END_DATE = new DateTime(2011, 1, 31);
            analysisRow.TIME_SCALE = (int)PSLibrary.TimeScaleClass.TimeScale.Months;
            analysisRow.BOOKING_TYPE = (int)PSLibrary.Resource.BookingType.Committed;
            analysisRow.HARD_CONSTRAINT_CF_UID = new Guid(HARD_CONSTRAINT_CF_GUID);

            portfolioAnalysisDS.Analysis.AddAnalysisRow(analysisRow);

            // Add a project to the Portfolio Analysis.
            SvcPortfolioAnalyses.AnalysisDataSet.AnalysisProjectsRow
                projectsRow =
                portfolioAnalysisDS.AnalysisProjects.NewAnalysisProjectsRow();

            projectsRow.ANALYSIS_UID = analysis_uid;
            projectsRow.PROJ_UID = new Guid(PROJECT_GUID);
            portfolioAnalysisDS.AnalysisProjects.AddAnalysisProjectsRow(
                projectsRow);

            Console.WriteLine("Creating analysis.....");
            jobGuid = Guid.NewGuid();

            try
            {
                analysesClient.QueueCreateAnalysis(portfolioAnalysisDS,
                    jobGuid);
                Helpers.WaitForQueue(SvcQueueSystem.QueueMsgType.AnalysisCreate,
                    1, queueSystemClient, jobGuid);
                Console.WriteLine("Analysis created successfully");
            }
            catch (CommunicationException e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(
                    "\n***System.ServiceModel.CommunicationException:");
                Console.WriteLine(e.ToString());
                Console.ResetColor();
            }
        }

        // Update the strategic impact data of a Portfolio Analysis.
        private static SvcPortfolioAnalyses.AnalysisDataSet UpdateAnalysis(
            Guid analysis_uid,
            Guid[] numDrivers,
            Guid jobGuid,
            SvcPortfolioAnalyses.AnalysisDataSet analysisDSAfterAdd)
        {
            // Update the impact values and update the analysis.

            // Look-up-table values for comparison (hard coded here).
            Guid[] lookUpTableValues = new Guid[2];
            Guid updateJobGuid = Guid.NewGuid();

            // Represents the "greater than" relationship.
            lookUpTableValues[0] =
                new Guid(GREATER_THAN_LOOKUPTABLE_VALUE);
            // Represents the "less than" relationship.
            lookUpTableValues[1] =
                new Guid(LESS_THAN_LOOKUPTABLE_VALUE);  // is <
            SvcPortfolioAnalyses.AnalysisDataSet.AnalysisProjectImpactRow
                relationRow = null;

            // If there is more than one project, do the following for all the projects.
            for (int j = 0; j < numDrivers.Count(); j++)
            {
                relationRow =
                    analysisDSAfterAdd.AnalysisProjectImpact.
                    NewAnalysisProjectImpactRow();
                relationRow.ANALYSIS_UID = analysis_uid;
                relationRow.LT_STRUCT_UID = lookUpTableValues[j];
                relationRow.PROJ_UID = new Guid(PROJECT_GUID);
                relationRow.DRIVER_UID = numDrivers[j];
                analysisDSAfterAdd.AnalysisProjectImpact.
                    AddAnalysisProjectImpactRow(
                    relationRow);
            }
            try
            {
                Console.WriteLine("Updating the analysis....");
                analysesClient.QueueUpdateAnalysis(analysisDSAfterAdd,
                    false, updateJobGuid);
                Helpers.WaitForQueue(SvcQueueSystem.QueueMsgType.AnalysisUpdate,
                    1, queueSystemClient, updateJobGuid);
                Console.WriteLine("Analysis updated successfully...");
            }
            catch (CommunicationException e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(
                    "\n***System.ServiceModel.CommunicationException:");
                Console.WriteLine(e.ToString());
                Console.ResetColor();
            }
            // Read the updated Portfolio Analysis.
            SvcPortfolioAnalyses.AnalysisDataSet analysisDSAfterUpdate =
                analysesClient.ReadAnalysis(analysis_uid);
            analysisDSAfterUpdate.WriteXml(outFilePathUpdatedAnalysisInfo);
            return analysisDSAfterUpdate;
        }

        // Configure the custom field client end points.
        public static void ConfigClientEndpoints(string endpt)
        {
            analysesClient = new SvcPortfolioAnalyses.PortfolioAnalysesClient(endpt);
        }
        // Configure the client end points.
        public static void SetClientEndpoints(string qendpt)
        {
            queueSystemClient = new SvcQueueSystem.QueueSystemClient(qendpt);
        }
    }

    class Helpers
    {
        /// <summary>
        /// Public TimeOut property
        /// </summary>
        /// <value>Gets/sets the timeout for WaitForQueue calls</value>
        public static int TimeOut
        {
            get
            {
                return timeOut;
            }
            set
            {
                timeOut = value;
            }
        }
        // Default time out is 3 minutes.
        private static int timeOut = 3 * 60 * 1000;

        // Incremental sleep time is 2 seconds.
        private static int incrementalSleepTime = 2 * 1000;

        public static SvcQueueSystem.JobState WaitForQueue(SvcQueueSystem.QueueMsgType jobType, int numJobs,
            SvcQueueSystem.QueueSystemClient queueSystemClient, Guid jobId)
        {
            int timeSlept = 0;
            int sleepInterval = (TimeOut / 60 > incrementalSleepTime) ? TimeOut / 60 : incrementalSleepTime;

            SvcQueueSystem.QueueStatusDataSet queueStatusDs = new SvcQueueSystem.QueueStatusDataSet();
            String errorString = String.Empty;
            Console.WriteLine("Waiting for job" + jobType.ToString());
            while (true)
            {
                SvcQueueSystem.JobState jobState = queueSystemClient.GetJobCompletionState(out errorString, jobId);

                SvcQueueSystem.QueueStatusDataSet jobStatus = queueSystemClient.ReadJobStatusSimple(new Guid[] { jobId }, true);
                if (jobState == SvcQueueSystem.JobState.Unknown)
                {
                    Console.WriteLine("Job status is unknown, may be the job was never placed on the Queue? - returning from WaitForQueue");
                    return jobState;
                }
                if (jobState == SvcQueueSystem.JobState.Success ||
                    jobState == SvcQueueSystem.JobState.Failed ||
                    jobState == SvcQueueSystem.JobState.FailedNotBlocking ||
                    jobState == SvcQueueSystem.JobState.CorrelationBlocked ||
                    jobState == SvcQueueSystem.JobState.Canceled)
                {
                    Console.WriteLine("Job completed, returning from WaitForQueue");
                    return jobState;
                }
                System.Threading.Thread.CurrentThread.Join(sleepInterval);
                timeSlept += sleepInterval;

                if (timeSlept > TimeOut)
                {
                    return SvcQueueSystem.JobState.Unknown;
                }
            }

        }

    }
}

See also

Reference

PortfolioAnalyses class

PortfolioAnalyses members

WebSvcPortfolioAnalyses namespace