Εργασία με λύσεις με χρήση των Dataverse SDK

Στο πλαίσιο του κύκλου ζωής από την ανάπτυξη στην παραγωγή, μπορεί να θέλετε να δημιουργήσετε προσαρμοσμένη αυτοματοποίηση για το χειρισμό ορισμένων εργασιών. Για παράδειγμα, στη διοχέτευση του έργου DevOps μπορεί να θέλετε να εκτελέσετε κάποιο προσαρμοσμένο κώδικα ή μια δέσμη ενεργειών που δημιουργεί ένα περιβάλλον προστατευμένης εκτέλεσης, εισαγάγει μια μη διαχειριζόμενη λύση, εξάγει αυτήν τη μη διαχειριζόμενη λύση ως διαχειριζόμενη λύση και, τέλος, διαγράφει το περιβάλλον. Μπορείτε να το κάνετε αυτό και πολλά άλλα χρησιμοποιώντας τα API που είναι στη διάθεσή σας. Ακολουθούν ορισμένα παραδείγματα για το τι μπορείτε να επιτύχετε χρησιμοποιώντας το Dataverse SDK για .NET και προσαρμοσμένο κώδικα.

Σημείωμα

Μπορείτε, επίσης, να εκτελέσετε αυτές τις ίδιες λειτουργίες χρησιμοποιώντας το Web API. Οι σχετικές ενέργειες είναι: ImportSolution, ExportSolution, CloneAsPatch και CloneAsSolution.

Δημιουργία, εξαγωγή ή εισαγωγή μη διαχειριζόμενης λύσης

Δείτε πώς μπορείτε να εκτελέσετε ορισμένες συνηθισμένες λειτουργίες λύσης χρησιμοποιώντας κώδικα C#. Για να προβάλετε το πλήρες δείγμα κώδικα C# που λειτουργεί, το οποίο δείχνει αυτούς τους τύπους λειτουργιών λύσης (και άλλα), ανατρέξτε στο θέμα Δείγμα: Εργασία με λύσεις.

Δημιουργία εκδότη

Κάθε λύση απαιτεί έναν εκδότη, ο οποίος εκπροσωπείται από την οντότητα εκδότη. Ένας εκδότης απαιτεί τα εξής:

  • Πρόθεμα προσαρμογής
  • Μοναδικό όνομα
  • Φιλικό όνομα

Σημείωμα

Για μια εύρυθμη προσέγγιση ALM, να χρησιμοποιείτε πάντα έναν προσαρμοσμένο εκδότη και μια λύση, όχι την προεπιλεγμένη λύση και τον εκδότη, για την ανάπτυξη των προσαρμογών σας.

Το ακόλουθο δείγμα κώδικα προσδιορίζει πρώτα έναν εκδότη και, στη συνέχεια, ελέγχει εάν ο εκδότης υπάρχει ήδη με βάση το μοναδικό όνομα. Εάν υπάρχει ήδη, το πρόθεμα προσαρμογής μπορεί να έχει αλλάξει, επομένως αυτό το δείγμα επιδιώκει να αποτυπώσει το τρέχον πρόθεμα προσαρμογής. Το PublisherId καταγράφεται επίσης έτσι ώστε να είναι δυνατή η διαγραφή της καρτέλας εκδότη. Αν ο εκδότης δεν βρεθεί, δημιουργείται ένας νέος εκδότης με χρήση της μεθόδου OrganizationService.Δημιουργία.

// 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.)
Σελίδα ρύθμισης παραμέτρων Εάν συμπεριλάβετε έναν πόρο Web 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 για να εξαγάγει ένα συμπιεσμένο αρχείο που αντιπροσωπεύει μια μη διαχειριζόμενη λύση. Η επιλογή δημιουργίας μιας διαχειριζόμενης λύσης ορίζεται χρησιμοποιώντας την ιδιότητα Διαχειριζόμενη. Αυτό το δείγμα αποθηκεύει ένα αρχείο με όνομα 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 για να καταγράψετε δεδομένα σχετικά με την επιτυχία της εισαγωγής της λύσης. Όταν καθορίζετε ένα ImportJobId για το ImportSolutionRequest, μπορείτε να χρησιμοποιήσετε αυτήν την τιμή για να υποβάλετε ερώτημα στην οντότητα εισαγωγής σχετικά με την κατάσταση της εισαγωγής. Το 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 compoent 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 για να προσδιορίσετε τυχόν άλλα στοιχεία λύσης, τα οποία θα απέτρεπαν τη διαγραφή ενός καθορισμένου στοιχείου λύσης. Το ακόλουθο δείγμα κώδικα αναζητά τα χαρακτηριστικά που χρησιμοποιούν έναν γνωστό καθολικό optionset. Κάθε χαρακτηριστικό που χρησιμοποιεί το καθολικό optionset θα απέτρεπε τη διαγραφή του καθολικού optionset.

// 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);
  }
 }
}