इसके माध्यम से साझा किया गया


Dataverse SDK का उपयोग करके समाधानों के साथ कार्य करें

विकास से उत्पादन जीवनचक्र के भाग के रूप में, हो सकता है कि आप कुछ कार्यों को संभालने के लिए कस्टम स्वचालन बनाना चाहें. उदाहरण के लिए, अपने DevOps प्रोजेक्ट पाइपलाइन में, हो सकता है कि आप कुछ ऐसे कस्टम कोड या स्क्रिप्ट निष्पादित करना चाहें जो सैंडबॉक्स परिवेश बनाता है, एक अप्रबंधित समाधान को आयात करता है, उस अप्रबंधित समाधान को प्रबंधित समाधान में निर्यात करता है, और अंत में, परिवेश को हटा देता है. आप, आपके लिए उपलब्ध APIs का उपयोग करके ऐसा और उससे ज़्यादा सकते हैं. नीचे कुछ उदाहरण दिए गए हैं कि आप Dataverse .NET के लिए SDK और कस्टम कोड का उपयोग करके क्या हासिल कर सकते हैं.

नोट

आप वेब API का उपयोग करके भी यही कार्य कर सकते हैं. संबंधित कार्रवाइयां हैं: ImportSolution, ExportSolution, CloneAsPatch, तथा CloneAsSolution.

एक अप्रबंधित समाधान बनाएँ, निर्यात करें, या आयात करें

आइए C# code का उपयोग करके कुछ सामान्य समाधान कार्यों को निष्पादित करने का तरीका देखें. इन प्रकार का समाधान कार्य (और अधिक) प्रदर्शित करने वाला C# कोड नमूना की पूरी प्रक्रिया देखने के लिए, नमूना: समाधानों के साथ कार्य करें देखें.

एक प्रकाशक बनाएँ

प्रत्येक समाधान के लिए एक प्रकाशक की आवश्यकता होती है, जिसका प्रतिनिधित्व प्रकाशक निकाय द्वारा किया जाता है. एक प्रकाशक को निम्नलिखित की आवश्यकता होती है:

  • एक अनुकूलन उपसर्ग
  • एक अद्वितीय नाम
  • एक परिचित नाम

नोट

एक स्वस्थ ALM दृष्टिकोण के लिए, अपने अनुकूलनों को परिनियोजित करने के लिए हमेशा एक कस्टम प्रकाशक और समाधान का उपयोग करें, न कि डिफ़ॉल्ट समाधान और प्रकाशक का.

निम्न कोड नमूना पहले एक प्रकाशक को परिभाषित करता है और फिर यह देखने के लिए जांच करता है कि प्रकाशक पहले से ही अद्वितीय नाम के आधार पर मौजूद है या नहीं. यदि यह पहले से मौजूद है, तो हो सकता है कि अनुकूलन उपसर्ग बदल दिया गया हो, इसलिए यह नमूना वर्तमान अनुकूलन उपसर्ग को कैप्चर करने का प्रयास करता है. PublisherId को भी कैप्चर किया जाता है ताकि प्रकाशक रिकॉर्ड को मिटाया जा सके. यदि प्रकाशक नहीं मिला है, तो एक नया प्रकाशक IOrganizationService का उपयोग करके बनाया गया है. बनाएं विधि.

// Define a new publisher
Publisher _myPublisher = new Publisher
{
   UniqueName = "contoso-publisher",
   FriendlyName = "Contoso publisher",
   SupportingWebsiteUrl =
      "https://learn.microsoft.com/powerapps/developer/data-platform/overview",
   CustomizationPrefix = "contoso",
   EMailAddress = "someone@contoso.com",
   Description = "This publisher was created from sample code"
};

// Does the publisher already exist?
QueryExpression querySamplePublisher = new QueryExpression
{
   EntityName = Publisher.EntityLogicalName,
   ColumnSet = new ColumnSet("publisherid", "customizationprefix"),
   Criteria = new FilterExpression()
};

querySamplePublisher.Criteria.AddCondition("uniquename", ConditionOperator.Equal,
   _myPublisher.UniqueName);

EntityCollection querySamplePublisherResults =
   _serviceProxy.RetrieveMultiple(querySamplePublisher);

Publisher SamplePublisherResults = null;

// If the publisher already exists, use it
if (querySamplePublisherResults.Entities.Count > 0)
{
   SamplePublisherResults = (Publisher)querySamplePublisherResults.Entities[0];
   _publisherId = (Guid)SamplePublisherResults.PublisherId;
   _customizationPrefix = SamplePublisherResults.CustomizationPrefix;
}

// If the publisher doesn't exist, create it
if (SamplePublisherResults == null)
{
   _publisherId = _serviceProxy.Create(_myPublisher);

   Console.WriteLine(String.Format("Created publisher: {0}.",
   _myPublisher.FriendlyName));

   _customizationPrefix = _myPublisher.CustomizationPrefix;
}

कोई अप्रबंधित समाधान बनाएँ

आपके पास कस्टम प्रकाशक उपलब्ध होने पर, आप इसके बाद एक अप्रबंधित समाधान बना सकते हैं. निम्नलिखित तालिका, एक समाधान में मौजूद फ़ील्ड को विवरणों के साथ सूचीबद्ध करती है.

फील्ड लेबल वर्णन
डिस्प्ले का नाम समाधान के लिए नाम.
नाम Microsoft Dataverse नाम प्रदर्शित करें के आधार पर एक अद्वितीय नाम उत्पन्न करता है. आप अद्वितीय नाम को संपादित कर सकते हैं. अद्वितीय नाम में केवल अल्फ़ान्यूमेरिक वर्ण या अंडरस्कोर वर्ण होने चाहिए.
प्रकाशक समाधान को प्रकाशक के साथ संबद्ध करने के लिए प्रकाशक लुकअप का उपयोग करें.
संस्करण निम्न स्वरूप का उपयोग करके कोई संस्करण निर्दिष्ट करें: major.minor.build.revision (उदाहरण के लिए, 1.0.0.0.
कॉन्फ़िगरेशन पृष्ठ यदि आप अपने समाधान में HTML वेब संसाधन शामिल करते हैं, तो आप इस लुकअप का उपयोग अपने निर्दिष्ट समाधान कॉन्फ़िगरेशन पेज के रूप में इसे जोड़ने के लिए कर सकते हैं.
वर्णन अपने समाधान के बारे में कोई भी प्रासंगिक विवरण शामिल करने के लिए इस फ़ील्ड का उपयोग करें.

एक अप्रबंधित समाधान बनाने के लिए नीचे नमूना कोड दिया गया है जो पिछले सेक्शन में हमारे द्वारा बनाए गए प्रकाशक का उपयोग करता है.

// Create a solution
Solution solution = new Solution
{
   UniqueName = "sample-solution",
   FriendlyName = "Sample solution",
   PublisherId = new EntityReference(Publisher.EntityLogicalName, _publisherId),
   Description = "This solution was created by sample code.",
   Version = "1.0"
};

// Check whether the solution already exists
QueryExpression queryCheckForSampleSolution = new QueryExpression
{
   EntityName = Solution.EntityLogicalName,
   ColumnSet = new ColumnSet(),
   Criteria = new FilterExpression()
};

queryCheckForSampleSolution.Criteria.AddCondition("uniquename",
   ConditionOperator.Equal, solution.UniqueName);

// Attempt to retrieve the solution
EntityCollection querySampleSolutionResults =
   _serviceProxy.RetrieveMultiple(queryCheckForSampleSolution);

// Create the solution if it doesn't already exist
Solution SampleSolutionResults = null;

if (querySampleSolutionResults.Entities.Count > 0)
{
   SampleSolutionResults = (Solution)querySampleSolutionResults.Entities[0];
   _solutionsSampleSolutionId = (Guid)SampleSolutionResults.SolutionId;
}

if (SampleSolutionResults == null)
{
   _solutionsSampleSolutionId = _serviceProxy.Create(solution);
}

आपके द्वारा अप्रबंधित समाधान बनाने के बाद, आप समाधान घटकों को इस समाधान के संदर्भ में बनाकर या अन्य समाधानों से मौजूदा घटकों को जोड़कर, उन्हें जोड़ सकते हैं. अधिक जानकारी: एक नया समाधान घटक जोड़ें तथा एक मौजूदा समाधान घटक जोड़ें

एक अप्रबंधित समाधान निर्यात करें

यह कोड नमूना एक अप्रबंधित समाधान को निर्यात करने या एक प्रबंधित समाधान को पैकेज करने का तरीका दिखाता है. कोड एक अप्रबंधित समाधान का प्रतिनिधित्व करने वाली कंप्रेस्ड फ़ाइल का निर्यात करने के लिए ExportSolutionRequestवर्ग का उपयोग करता है. एक प्रबंधित समाधान बनाने का विकल्प Managed गुण का उपयोग करके सेट किया गया है. यह नमूना आउटपुट फ़ोल्डर में samplesolution.zip नाम की फ़ाइल सहेजता है.

// Export a solution
ExportSolutionRequest exportSolutionRequest = new ExportSolutionRequest();
exportSolutionRequest.Managed = false;
exportSolutionRequest.SolutionName = solution.UniqueName;

ExportSolutionResponse exportSolutionResponse =
   (ExportSolutionResponse)_serviceProxy.Execute(exportSolutionRequest);

byte[] exportXml = exportSolutionResponse.ExportSolutionFile;
string filename = solution.UniqueName + ".zip";

File.WriteAllBytes(outputDir + filename, exportXml);

Console.WriteLine("Solution exported to {0}.", outputDir + filename);

एक अप्रबंधित समाधान आयात करें

कोड का उपयोग करके एक समाधान को आयात करना (या अपग्रेड करना) ImportSolutionRequest की मदद से पूरा किया जाता है.

// Install or upgrade a solution
byte[] fileBytes = File.ReadAllBytes(ManagedSolutionLocation);

ImportSolutionRequest impSolReq = new ImportSolutionRequest()
{
   CustomizationFile = fileBytes
};

_serviceProxy.Execute(impSolReq);

आयात की सफलता को ट्रैक करना

आप समाधान को आयात करने की सफलता का डेटा कैप्चर करने के लिए ImportJob निकाय का उपयोग कर सकते हैं. जब आप ImportSolutionRequest के लिए ImportJobId निर्दिष्ट करते हैं, तो आप आयात की स्थिति के बारे में ImportJob निकाय से क्वेरी करने के लिए उस मान का उपयोग कर सकते हैं. ImportJobIdका उपयोग RetrieveFormattedImportJobResultsRequest संदेश का उपयोग करके आयात लॉग फ़ाइल को डाउनलोड करने के लिए भी किया जा सकता है.

// Monitor solution import success
byte[] fileBytesWithMonitoring = File.ReadAllBytes(ManagedSolutionLocation);

ImportSolutionRequest impSolReqWithMonitoring = new ImportSolutionRequest()
{
   CustomizationFile = fileBytes,
   ImportJobId = Guid.NewGuid()
};

_serviceProxy.Execute(impSolReqWithMonitoring);

ImportJob job = (ImportJob)_serviceProxy.Retrieve(ImportJob.EntityLogicalName,
   impSolReqWithMonitoring.ImportJobId, new ColumnSet(new System.String[] { "data",
   "solutionname" }));

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(job.Data);

String ImportedSolutionName =
   doc.SelectSingleNode("//solutionManifest/UniqueName").InnerText;

String SolutionImportResult =
   doc.SelectSingleNode("//solutionManifest/result/\@result").Value;

Console.WriteLine("Report from the ImportJob data");

Console.WriteLine("Solution Unique name: {0}", ImportedSolutionName);

Console.WriteLine("Solution Import Result: {0}", SolutionImportResult);

Console.WriteLine("");

// This code displays the results for Global Option sets installed as part of a
// solution.

System.Xml.XmlNodeList optionSets = doc.SelectNodes("//optionSets/optionSet");

foreach (System.Xml.XmlNode node in optionSets)
{
   string OptionSetName = node.Attributes["LocalizedName"].Value;
   string result = node.FirstChild.Attributes["result"].Value;

   if (result == "success")
   {
      Console.WriteLine("{0} result: {1}",OptionSetName, result);
   }
   else
   {
      string errorCode = node.FirstChild.Attributes["errorcode"].Value;
      string errorText = node.FirstChild.Attributes["errortext"].Value;

      Console.WriteLine("{0} result: {1} Code: {2} Description: {3}",OptionSetName,
      result, errorCode, errorText);
   }
}

Data गुण की सामग्री, समाधान XML फ़ाइल को दर्शाने वाली एक स्ट्रिंग है.

समाधान घटक को जोड़ें और निकालें

कोड का उपयोग करके समाधान घटकों को जोड़ना और हटाना सीखें.

एक नया समाधान घटक जोड़ें

यह नमूना दिखाता है कि एक ऐसा समाधान घटक कैसे बनाया जाए जो किसी विशिष्ट समाधान से जुड़ा हो. यदि आप समाधान घटक को किसी विशिष्ट समाधान से नहीं जोड़ते हैं, जब इसे बनाया जाता है, तो इसे केवल डिफ़ॉल्ट समाधान में जोड़ा जाएगा और आपको इसे मैन्युअल रूप से या कोई मौजूदा समाधान घटक जोड़े में शामिल कोड का उपयोग करके जोड़ना होगा.

यह कोड एक नया वैश्विक विकल्प सेट बनाता है और इसे _primarySolutionName के बराबर एक अद्वितीय नाम के साथ समाधान में जोड़ता है.

OptionSetMetadata optionSetMetadata = new OptionSetMetadata()
{
   Name = _globalOptionSetName,
   DisplayName = new Label("Example Option Set", _languageCode),
   IsGlobal = true,
   OptionSetType = OptionSetType.Picklist,
   Options =
{
   new OptionMetadata(new Label("Option 1", _languageCode), 1),
   new OptionMetadata(new Label("Option 2", _languageCode), 2)
}
};
CreateOptionSetRequest createOptionSetRequest = new CreateOptionSetRequest
{
   OptionSet = optionSetMetadata                
};

createOptionSetRequest.SolutionUniqueName = _primarySolutionName;
_serviceProxy.Execute(createOptionSetRequest);

एक मौजूदा समाधान घटक जोड़ें

यह नमूना दिखाता है कि किसी समाधान में किसी मौजूदा समाधान घटक को कैसे जोड़ते हैं.

निम्नलिखित कोड AddSolutionComponentRequest का उपयोग Account निकाय को अप्रबंधित समाधान के समाधान घटक के रूप में जोड़ने के लिए करता है.

// Add an existing Solution Component
// Add the Account entity to the solution
RetrieveEntityRequest retrieveForAddAccountRequest = new RetrieveEntityRequest()
{
   LogicalName = Account.EntityLogicalName
};
RetrieveEntityResponse retrieveForAddAccountResponse = (RetrieveEntityResponse)_serviceProxy.Execute(retrieveForAddAccountRequest);
AddSolutionComponentRequest addReq = new AddSolutionComponentRequest()
{
   ComponentType = (int)componenttype.Entity,
   ComponentId = (Guid)retrieveForAddAccountResponse.EntityMetadata.MetadataId,
   SolutionUniqueName = solution.UniqueName
};
_serviceProxy.Execute(addReq);

समाधान घटक निकालें

यह नमूना दिखाता है कि किसी अप्रबंधित समाधान से समाधान घटक को कैसे हटाना है. निम्नलिखित कोड निकाय समाधान घटक को अप्रबंधित समाधान से हटाने के लिए RemoveSolutionComponentRequest का उपयोग करता है. solution.UniqueName अप्रबंधित समाधान बनाएं में बनाए गए समाधान को संदर्भित करता है.

// Remove a Solution Component
// Remove the Account entity from the solution
RetrieveEntityRequest retrieveForRemoveAccountRequest = new RetrieveEntityRequest()
{
   LogicalName = Account.EntityLogicalName
};
RetrieveEntityResponse retrieveForRemoveAccountResponse = (RetrieveEntityResponse)_serviceProxy.Execute(retrieveForRemoveAccountRequest);

RemoveSolutionComponentRequest removeReq = new RemoveSolutionComponentRequest()
{
   ComponentId = (Guid)retrieveForRemoveAccountResponse.EntityMetadata.MetadataId,
   ComponentType = (int)componenttype.Entity,
   SolutionUniqueName = solution.UniqueName
};
_serviceProxy.Execute(removeReq);

कोई समाधान हटाएँ

निम्नलिखित नमूना दिखाता है कि समाधान uniquename का उपयोग करके समाधान कैसे प्राप्त करते हैं और फिर परिणामों से solutionid कैसे निकालते हैं. नमूना फिर solutionid को IOrganizationService के साथ उपयोग करता है. Delete समाधान को हटाने की विधि.

// Delete a solution

QueryExpression queryImportedSolution = new QueryExpression
{
    EntityName = Solution.EntityLogicalName,
    ColumnSet = new ColumnSet(new string[] { "solutionid", "friendlyname" }),
    Criteria = new FilterExpression()
};


queryImportedSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, ImportedSolutionName);

Solution ImportedSolution = (Solution)_serviceProxy.RetrieveMultiple(queryImportedSolution).Entities[0];

_serviceProxy.Delete(Solution.EntityLogicalName, (Guid)ImportedSolution.SolutionId);

Console.WriteLine("Deleted the {0} solution.", ImportedSolution.FriendlyName);

क्लोनिंग, पैचिंग और अपग्रेडिंग

आप उपलब्ध API का उपयोग करके अतिरिक्त समाधान संचालन कर सकते हैं. क्लोनिंग और पैचिंग समाधान के लिए CloneAsPatchRequest और CloneAsSolutionRequest का उपयोग करें. क्लोनिंग और पैचिंग के बारे में जानकारी के लिए, समाधान पैच बनाएँ देखें.

समाधान अपग्रेड करते समय StageAndUpgradeRequest और DeleteAndPromoteRequest का उपयोग करें. स्टेजिंग की प्रक्रिया और अपग्रेड्स के बारे में अधिक जानकारी के लिए, समाधान को अपग्रेड या अपडेट करें देखें.

समाधान निर्भरताओं का पता लगाएँ

यह नमूना दिखाता है कि समाधान घटकों के बीच निर्भरता दिखाने वाली रिपोर्ट कैसे बनाई जाती है.

यह कोड होगा:

  • किसी समाधान के लिए सभी घटक को प्राप्त करें.

  • प्रत्येक घटक के लिए सभी निर्भरताएँ प्राप्त करें.

  • पायी गई प्रत्येक निर्भरता के लिए, निर्भरता का वर्णन करने वाली रिपोर्ट प्रदर्शित करें.

// Grab all Solution Components for a solution.
QueryByAttribute componentQuery = new QueryByAttribute
{
    EntityName = SolutionComponent.EntityLogicalName,
    ColumnSet = new ColumnSet("componenttype", "objectid", "solutioncomponentid", "solutionid"),
    Attributes = { "solutionid" },

    // In your code, this value would probably come from another query.
    Values = { _primarySolutionId }
};

IEnumerable<SolutionComponent> allComponents =
    _serviceProxy.RetrieveMultiple(componentQuery).Entities.Cast<SolutionComponent>();

foreach (SolutionComponent component in allComponents)
{
    // For each solution component, retrieve all dependencies for the component.
    RetrieveDependentComponentsRequest dependentComponentsRequest =
        new RetrieveDependentComponentsRequest
        {
            ComponentType = component.ComponentType.Value,
            ObjectId = component.ObjectId.Value
        };
    RetrieveDependentComponentsResponse dependentComponentsResponse =
        (RetrieveDependentComponentsResponse)_serviceProxy.Execute(dependentComponentsRequest);

    // If there are no dependent components, we can ignore this component.
    if (dependentComponentsResponse.EntityCollection.Entities.Any() == false)
        continue;

    // If there are dependencies upon this solution component, and the solution
    // itself is managed, then you will be unable to delete the solution.
    Console.WriteLine("Found {0} dependencies for Component {1} of type {2}",
        dependentComponentsResponse.EntityCollection.Entities.Count,
        component.ObjectId.Value,
        component.ComponentType.Value
        );
    //A more complete report requires more code
    foreach (Dependency d in dependentComponentsResponse.EntityCollection.Entities)
    {
        DependencyReport(d);
    }
}

DependencyReport विधि निम्नलिखित कोड नमूने में है.

निर्भरता रिपोर्ट

DependencyReport विधि निर्भरता के भीतर मिली जानकारी के आधार पर एक मैत्रीपूर्ण संदेश प्रदान करती है.

नोट

इस नमूने में तरीका केवल आंशिक रूप से लागू है. यह केवल ए़ट्रिब्यूट और विकल्प सेट समाधान घटकों के लिए संदेश प्रदर्शित कर सकता है.

/// <summary>
/// Shows how to get a more friendly message based on information within the dependency
/// <param name="dependency">A Dependency returned from the RetrieveDependentComponents message</param>
/// </summary> 
public void DependencyReport(Dependency dependency)
{
 // These strings represent parameters for the message.
    String dependentComponentName = "";
    String dependentComponentTypeName = "";
    String dependentComponentSolutionName = "";
    String requiredComponentName = "";
    String requiredComponentTypeName = "";
    String requiredComponentSolutionName = "";

 // The ComponentType global Option Set contains options for each possible component.
    RetrieveOptionSetRequest componentTypeRequest = new RetrieveOptionSetRequest
    {
     Name = "componenttype"
    };

    RetrieveOptionSetResponse componentTypeResponse = (RetrieveOptionSetResponse)_serviceProxy.Execute(componentTypeRequest);
    OptionSetMetadata componentTypeOptionSet = (OptionSetMetadata)componentTypeResponse.OptionSetMetadata;
 // Match the Component type with the option value and get the label value of the option.
    foreach (OptionMetadata opt in componentTypeOptionSet.Options)
    {
     if (dependency.DependentComponentType.Value == opt.Value)
     {
      dependentComponentTypeName = opt.Label.UserLocalizedLabel.Label;
     }
     if (dependency.RequiredComponentType.Value == opt.Value)
     {
      requiredComponentTypeName = opt.Label.UserLocalizedLabel.Label;
     }
    }
 // The name or display name of the component is retrieved in different ways depending on the component type
    dependentComponentName = getComponentName(dependency.DependentComponentType.Value, (Guid)dependency.DependentComponentObjectId);
    requiredComponentName = getComponentName(dependency.RequiredComponentType.Value, (Guid)dependency.RequiredComponentObjectId);

 // Retrieve the friendly name for the dependent solution.
    Solution dependentSolution = (Solution)_serviceProxy.Retrieve
     (
      Solution.EntityLogicalName,
      (Guid)dependency.DependentComponentBaseSolutionId,
      new ColumnSet("friendlyname")
     );
    dependentComponentSolutionName = dependentSolution.FriendlyName;
    
 // Retrieve the friendly name for the required solution.
    Solution requiredSolution = (Solution)_serviceProxy.Retrieve
      (
       Solution.EntityLogicalName,
       (Guid)dependency.RequiredComponentBaseSolutionId,
       new ColumnSet("friendlyname")
      );
    requiredComponentSolutionName = requiredSolution.FriendlyName;

 // Display the message
     Console.WriteLine("The {0} {1} in the {2} depends on the {3} {4} in the {5} solution.",
     dependentComponentName,
     dependentComponentTypeName,
     dependentComponentSolutionName,
     requiredComponentName,
     requiredComponentTypeName,
     requiredComponentSolutionName);
}

पता करें कि क्या कोई समाधान घटक हटाया जा सकता है

किसी अन्य समाधान घटकों की पहचान करने के लिए RetrieveDependenciesForDeleteRequest संदेश का उपयोग करें, जो किसी दिए गए समाधान घटक को हटाए जाने से रोक देगा. निम्नलिखित कोड नमूना किसी ज्ञात वैश्विक विकल्पसेट का उपयोग करके किसी भी एट्रिब्यूट को खोजता है. वैश्विक विकल्पसेट का उपयोग करने वाली कोई भी एट्रिब्यूट, वैश्विक विकल्पसेट को हटाए जाने से रोकती है.

// Use the RetrieveOptionSetRequest message to retrieve  
// a global option set by it's name.
RetrieveOptionSetRequest retrieveOptionSetRequest =
    new RetrieveOptionSetRequest
    {
     Name = _globalOptionSetName
    };

// Execute the request.
RetrieveOptionSetResponse retrieveOptionSetResponse =
    (RetrieveOptionSetResponse)_serviceProxy.Execute(
    retrieveOptionSetRequest);
_globalOptionSetId = retrieveOptionSetResponse.OptionSetMetadata.MetadataId;
if (_globalOptionSetId != null)
{ 
 // Use the global OptionSet MetadataId with the appropriate componenttype
 // to call RetrieveDependenciesForDeleteRequest
 RetrieveDependenciesForDeleteRequest retrieveDependenciesForDeleteRequest = new RetrieveDependenciesForDeleteRequest 
{ 
 ComponentType = (int)componenttype.OptionSet,
 ObjectId = (Guid)_globalOptionSetId
};

 RetrieveDependenciesForDeleteResponse retrieveDependenciesForDeleteResponse =
  (RetrieveDependenciesForDeleteResponse)_serviceProxy.Execute(retrieveDependenciesForDeleteRequest);
 Console.WriteLine("");
 foreach (Dependency d in retrieveDependenciesForDeleteResponse.EntityCollection.Entities)
 {

  if (d.DependentComponentType.Value == 2)//Just testing for Attributes
  {
   String attributeLabel = "";
   RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest
   {
    MetadataId = (Guid)d.DependentComponentObjectId
   };
   RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)_serviceProxy.Execute(retrieveAttributeRequest);

   AttributeMetadata attmet = retrieveAttributeResponse.AttributeMetadata;

   attributeLabel = attmet.DisplayName.UserLocalizedLabel.Label;
  
    Console.WriteLine("An {0} named {1} will prevent deleting the {2} global option set.", 
   (componenttype)d.DependentComponentType.Value, 
   attributeLabel, 
   _globalOptionSetName);
  }
 }
}