Märkus.
Juurdepääs sellele lehele nõuab autoriseerimist. Võite proovida sisse logida või kausta vahetada.
Juurdepääs sellele lehele nõuab autoriseerimist. Võite proovida kausta vahetada.
Oma arendusest tootmisse ülemineku elutsükli osana võiksite luua kohandatud automatiseeringuid teatud ülesannete täitmiseks. Näiteks kui soovite oma DevOpsi projekti konveieril käivitada mõne kohandatud koodi või skripti, mis loob liivakastikeskkonna, impordib mittehallatava lahenduse, ekspordib mittehallatava lahenduse hallatava lahendusena ja lõpuks kustutab keskkonna. Saate neid ja muid toiminguid teha teile saadaolevate API-de abil. Siin on mõned näited selle kohta, mida saate .NET-i .DK Dataverse ja kohandatud koodi abil saavutada.
Märkus.
Samu toiminguid saate teha ka veebi API abil. Seostuvad toimingud on järgmised: ImportSolution, ExportSolution, CloneAsPatch ja CloneAsSolution.
Selle artikli koodinäidised kasutavad varakult seotud olemitüüpe, mis on loodud kas CrmSvcUtili või PAC CLI abil. Lisateave: Hilises ja varajases köites programmeerimine .NET SDK abil
Mittehallatava lahenduse loomine, eksportimine või importimine
Siit saad teada, kuidas C# koodi abil mõningaid levinud lahendustoiminguid sooritada. Täieliku toimiva C# koodinäidise vaatamiseks, mis demonstreerib seda tüüpi lahendustoiminguid ja muud, minge lehele Näide: Lahendustega töötamine.
Väljastaja loomine
Iga lahendus vajab avaldajat, mida esindab avaldaja tabel . Väljaandja vajab järgmisi omadusi:
- Kohandamise eesliide
- Kordumatu nimetus
- Sõbralik nimi
Märkus.
Tervisliku rakenduse elutsükli halduse (ALM) lähenemisviisi jaoks kasutage kohanduste juurutamiseks alati kohandatud väljaandjat ja lahendust, mitte vaikelahendust ja -väljaandjat.
Järgnev koodinäidis määratleb esmalt avaldaja ja kontrollib seejärel unikaalse nime põhjal, kas avaldaja on juba olemas. Kui see on juba olemas, võib kohanduse eesliide olla muudetud. See näidis püüab jäädvustada praegust kohandamise eesliidet. Samuti hõivatakse PublisherId nii, et väljastaja kirjet saaks kustutada. Kui väljastajat ei leita, luuakse uus väljastajaIOrganizationService.Loo meetodi abil.
// 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;
}
Mittehallatava lahenduse loomine
Kui teie kohandatud väljastaja on saadaval, saate luua mittehallatava lahenduse. Järgmises tabelis on loetletud lahenduse veerud koos kirjeldustega.
| Veeru silt | Kirjeldus |
|---|---|
| Kuvatav nimetus | Lahenduse nimi. |
| Nimetus | Microsoft Dataverse loob kordumatu nimeKuvatava nime põhjal. Saate kordumatut nime redigeerida. Kordumatu nimi peab sisaldama ainult tähe- ja numbrimärke ning allkriipse. |
| Väljaandja | Lahenduse seostamiseks väljastajaga kasutage otsingut Väljastaja. |
| Versioon | Määrake versioon järgmises vormingus: major.minor.build.revision, näiteks 1.0.0.0. |
| Konfiguratsiooni leht | Kui lisate lahendusse HTML-i veebiressursi, saate selle otsingu abil lisada selle teie määratud lahenduse konfiguratsiooni lehele. |
| Kirjeldus | Kasutage seda veergu, et lisada oma lahenduse kohta kõik asjakohased üksikasjad. |
Siin on näidiskood mittehallatava lahenduse loomiseks, mis kasutab eelmises jaotises loodud avaldajat.
// 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);
}
Pärast mittehallatava lahenduse loomist saate lahenduse komponente lisada, luues need selle lahenduse kontekstis või lisades olemasolevaid komponente teistest lahendustest. Lisateave. Uue lahenduse komponendi lisamine ja Olemasoleva lahenduse komponendi lisamine
Mittehallatava lahenduse eksportimine
Selle koodi näidise abil näete, kuidas mittehallatavat lahendust eksportida või hallatavat lahendust pakkida. Kood kasutab klassi ExportSolutionRequest mittehallatavat lahendust tähistava tihendatud faili eksportimiseks. Hallatava lahenduse loomise suvand määratakse atribuudi Hallatav abil. Selles näites salvesttakse faili nimega samplesolution.zip väljund kausta.
// 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);
Mittehallatava lahenduse importimine
Koodi abil lahenduse importimine (või täiendamine) toimub üksuse ImportSolutionRequest abil.
// Install or upgrade a solution
byte[] fileBytes = File.ReadAllBytes(ManagedSolutionLocation);
ImportSolutionRequest impSolReq = new ImportSolutionRequest()
{
CustomizationFile = fileBytes
};
_serviceProxy.Execute(impSolReq);
Impordi õnnestumise jälgimine
Lahenduse impordi edukuse kohta andmete jäädvustamiseks saate kasutada tabelit ImportJob. Kui määrate ImportSolutionRequest ImportJobId taotluse jaoks väärtuse , saate seda väärtust kasutada impordi oleku kohta tabelist ImportJob päringu esitamiseks. Üksust ImportJobId saab kasutada ka impordi logifaili allalaadimiseks sõnumi RetrieveFormattedImportJobResultsRequest abil.
// 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);
}
}
Atribuudi Data sisuks on string, mis tähistab lahenduse XML-faili.
Lahendusekomponentide lisamine või eemaldamine
Siit saate teada, kuidas koodi abil lahenduse komponente lisada ja eemaldada.
Uue lahendusekomponendi lisamine
See näide selgitab, kuidas luua kindla lahendusega seostatud lahenduse komponenti. Kui te ei seosta lahenduse komponenti loomisel kindla lahendusega, lisatakse see ainult vaikelahendusele ja peate selle lahendusele lisama käsitsi või jaotises **Olemasoleva lahenduse komponendi lisamine** oleva koodi abil. ...
See kood loob uue globaalse suvandikomplekti ja lisab selle lahendusele, mille kordumatu nimi on _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);
Olemasoleva lahenduse komponendi lisamine lahendusele
See näide selgitab, kuidas lisada lahendusele olemasolevat lahenduse komponenti.
Järgnev kood kasutab tabeli AddSolutionComponentRequest lisamiseks lahenduse komponendina mittehallatavale lahendusele. 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);
Lahenduse komponendi eemaldamine
See näide selgitab, kuidas eemaldada lahenduse komponent mittehallatavast lahendusest. Järgnev kood kasutab tabeli lahenduse komponendi eemaldamiseks mittehallatavast lahendusest funktsiooni RemoveSolutionComponentRequest .
solution.UniqueName viitab jaotises Mittehallatava lahenduse loomine loodud lahendusele.
// 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);
Lahenduse kustutamine
Järgmine näide selgitab, kuidas tuua lahendus, kasutades lahendust uniquename, ja seejärel ekstraktida tulemitest solutionid. Seejärel kasutatakse näites lahenduse ID-d solutionid ja sõnumit IOrganizationService.
Delete Lahenduse kustutamise meetod.
// 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);
Kloonimine, paikamine ja täiendamine
Saadaolevate API-de abil saate teha täiendavaid lahenduse toiminguid. Kloonimis- ja paigamislahenduste jaoks kasutage taotlusi CloneAsPatchRequest ja CloneAsSolutionRequest. Teavet kloonimise ja paikamise kohta leiate teemast Lahenduse paikade loomine.
Lahenduse versiooni täiendamiseks kasutage järgmisi: StageAndUpgradeRequest ja DeleteAndPromoteRequest. Lisateavet lahenduse ettevalmistamise ja uuendamise protsessi kohta leiate jaotisest Lahenduse uuendamine.
Lahendusesõltuvuste tuvastamine
See näide selgitab, kuidas luua aruanne, mis näitab lahenduse komponentide vahelisi sõltuvussuhteid.
See kood teostab järgmisi toiminguid:
Toob lahenduse kõik komponendid.
Toob iga komponendi kõik sõltuvused.
Kuvab sõltuvussuhet kirjeldava aruande iga leitud sõltuvuse kohta.
// 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);
}
}
Meetod DependencyReport on järgmises koodi näites.
Sõltuvussuhte aruanne
Meetod DependencyReport pakub sõbralikumat sõnumit, mis põhineb sõltuvuse teabel.
Märkus.
Selles näites rakendatakse seda meetodit ainult osaliselt. Selles saab kuvada ainult atribuutide ja suvandikomplekti lahenduse komponentide sõnumeid.
/// <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);
}
Lahenduse komponendi kustutamise võimalikkuse tuvastamine
Kasutage sõnumit RetrieveDependenciesForDeleteRequest, et tuvastada kõik muud lahenduse komponendid, mis võivad takistada konkreetse lahenduse komponendi kustutamist. Järgnev koodinäidis otsib atribuute teadaoleva globaalse valiku veeru abil. Iga globaalset valikut kasutav atribuut takistab globaalse valiku kustutamist.
// 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);
}
}
}