Freigeben über


Aktualisieren und Löschen von Tabellenzeilen über die SDK für .NET

Dieseser Artikel enthält Beispiele zu später und früherer gebundenen Programmierungsstilen. Weitere Informationen: Programmierung mit später und früher Bindung mithilfe des SDK für .NET

Jedes der Beispiele verwendet eine svc-Variable, die eine Instanz einer Klasse darstellt, die Sie auf IOrganizationService der Benutzeroberfläche implementieren. Weitere Informationen zu Klassen finden Sie unter Organisationsservice-Benutzeroberfläche.

Wichtig

Beziehen Sie beim Aktualisieren einer Tabellenzeile nur die Spalten ein, die Sie ändern. Durch einfaches Aktualisieren der Spalten einer zuvor abgerufenen Tabellenzeile wird jede Spalte aktualisiert, auch wenn der Wert unverändert ist. Dies kann Systemereignisse verursachen, die Geschäftslogik starten können, da angenommen wird, dass die Werte geändert haben. Dies kann auch dazu führen, dass Spalten in Überwachungsdaten scheinbar aktualisiert wurden, obwohl sie sich tatsächlich nicht geändert haben.

Sie sollten eine neue Entity-Instanz erstellen, das ID-Attribut und alle Attributwerte festlegen, die Sie ändern, und diese Entitätsinstanz zur Aktualisierung der Tabellenzeile verwenden.

Anmerkung

Die Spaltendefinition enthält eine Eigenschaft RequiredLevel. Wenn diese auf SystemRequired festgelegt ist, können Sie diese Spalten nicht auf einen Nullwert setzen. Wenn Sie dies versuchen, erhalten Sie den Fehlercode -2147220989 mit der Meldung Attribute: <attribute name> cannot be set to NULL.

Weitere Informationen: Erforderlichkeitsstufe für Spalten (Attribut)

Grundlegende Aktualisierung

In den beiden folgenden Beispielen wird die IOrganizationService.Update-Methode verwendet, um Spaltenwerte für eine zuvor abgerufene Tabellenzeile festzulegen.

Nutzen Sie die Entity.Id-Eigenschaft, um den eindeutigen Bezeichnerwert der abgerufenen Zeile der Entitätsinstanz zu übertragen, die verwendet wird, um den Vorgang zu aktualisieren.

Anmerkung

Wenn Sie versuchen, eine Zeile ohne Primärschlüsselwert zu aktualisieren, erhalten Sie folgende Fehlermeldung: Entity Id must be specified for Update.

Wenn Sie keinen Primärschlüsselwert haben, können Sie Zeilen auch mit Alternativschlüsseln aktualisieren. Weitere Informationen: Update mit Alternativschlüssel

Das folgende Bespiel zeigt, wie mit der Entitätsklasse ein Konto anhand der IOrganizationService.Update-Methode erstellt wird.

var retrievedAccount = new Entity("account", new Guid("a976763a-ba1c-e811-a954-000d3af451d6"));

//Use Entity class with entity logical name
var account = new Entity("account");
account.Id = retrievedAccount.Id;
// set attribute values
// Boolean (Two option)
account["creditonhold"] = true;
// DateTime
account["lastonholdtime"] = DateTime.Now;
// Double
account["address1_latitude"] = 47.642311;
account["address1_longitude"] = -122.136841;
// Int
account["numberofemployees"] = 400;
// Money
account["revenue"] = new Money(new Decimal(2000000.00));
// Picklist (Option set)
account["accountcategorycode"] = new OptionSetValue(2); //Standard customer

//Update the account
svc.Update(account);

Die UpdateRequest-Klasse

Anstatt die IOrganizationService.Update-Methode zu nutzen, können Sie entweder die späte Entitätsklassen oder die früh gebundenen Entitätsklassen mit der UpdateRequest-Klasse nutzen, indem Sie die Entitätsinstanz auf UpdateRequest.Target-Eigenschaft festlegen und dann die IOrganizationService.Execute-Methode nutzen, um ein Beispiel zu erhalten.

Anmerkung

Die UpdateResponse-Klasse weiste keine Eigenschaften auf. Während sie mit der IOrganizationService.Execute-Methode zurückgegeben wird, ist es nicht nötig, darauf zu referenzieren.

var request = new UpdateRequest()
{ Target = account };
svc.Execute(request);

Wedd ie UpdateRequest-Klasse verwendet werden soll

Sie müssen die UpdateRequest-Klasse verwenden, wenn Sie optionale Parameter behalten möchten. Es gibt zwei Fälle, in denen Sie möglicherweise bestimmte Parameter brauchen.

Sie müssen die verwenden Klasse auch UpdateRequest nutzen, wenn Sie einem Verhalten eine optimistische Parallelität angeben möchten. Weitere Informationen: Verhalten der optimistischen Parallelität

UpdateMultipleRequest-Klasse verwenden

Die UpdateMultipleRequest-Klasse ist die leistungsstärkste Möglichkeit, mehrere Datensätze in einer einzelnen Anforderung zu aktualisieren. Weitere Informationen: Nachrichten zu Massenvorgängen

Auf ähnliche Weise, wie Sie verknüpfte Tabellenzeilen in einem Vorgang erstellen können, können Sie zugehörige Tabellenzeilen auch aktualisieren.

Um die zugehörigen Tabellenzeilen zu aktualisieren, müssen Sie eine Zeile mit den zugehörigen Zeilen abrufen, damit Sie auf die ID-Werte zugreifen können. Weitere Informationen: Abrufen mit Bezugszeilen

Wichtig

Zeilen werden in einer bestimmten Reihenfolge aktualisiert. Zuerst werden primäre Tabellenzeilen verarbeitet und dann verknüpfte Tabellenzeilen. Wenn von der primären Zeile für eine Nachschlage- oder eine zugehörige Zeilenspalte eine Änderung vorgenommen wird und eine zugehörige Zeile anschließend dieselbe Spalte aktualisiert, wird der zugehörige Zeilenwert beibehalten. Im Allgemeinen sollten ein Nachschlagespaltenwert und sein Äquivalent in Entity.RelatedEntities für dieselbe Beziehung nicht gleichzeitig verwendet werden.

var account = new Entity("account");
account.Id = retrievedAccount.Id;

//Define relationships
var primaryContactRelationship = new Relationship("account_primary_contact");
var AccountTasksRelationship = new Relationship("Account_Tasks");

//Update the account name
account["name"] = "New Account name";

//Update the email address for the primary contact of the account
var contact = new Entity("contact");
contact.Id = retrievedAccount.RelatedEntities[primaryContactRelationship]
.Entities.FirstOrDefault().Id;
contact["emailaddress1"] = "someone_a@example.com";

List<Entity> primaryContacts = new List<Entity>();
primaryContacts.Add(contact);  
account.RelatedEntities.Add(primaryContactRelationship, new EntityCollection(primaryContacts));

// Find related Tasks that need to be updated
List<Entity> tasksToUpdate = retrievedAccount
.RelatedEntities[AccountTasksRelationship].Entities
.Where(t => t["subject"].Equals("Example Task")).ToList();

// A list to put the updated tasks
List<Entity> updatedTasks = new List<Entity>();

//Fill the list of updated tasks based on the tasks that need to but updated
tasksToUpdate.ForEach(t => {
var updatedTask = new Entity("task");
updatedTask.Id = t.Id;
updatedTask["subject"] = "Updated Subject";

updatedTasks.Add(updatedTask);
});

//Set the updated tasks to the collection
account.RelatedEntities.Add(AccountTasksRelationship, new EntityCollection(updatedTasks));

//Update the account and related contact and tasks
svc.Update(account);

Nach doppelten Datensätzen suchen

Beim Aktualisieren einer Tabellenzeile können Sie die Werte ändern, sodass die Zeile ein Duplikat einer anderen Zeile darstellt. Weitere Informationen: Erkennen von doppelten Daten mit dem SDK für .NET

Aktualisierung mit Alternativschlüsseln

Wenn für eine Tabelle ein Alternativschlüssel definiert ist, können Sie diesen anstelle des Primärschlüssels verwenden, um eine Zeile zu aktualisieren. Sie können die früh gebundene Klasse nicht verwendet, um den Alternativschlüssel anzugeben. Sie müssen den Konstruktor Entity(String, KeyAttributeCollection) verwenden, um den Alternativschlüssel anzugeben.

Bei Nutzung von Typen mit früher Bindung können Sie Entity mittels der Entity.ToEntity<T>-Methode in eine führ gebundene Klasse konvertieren.

Das folgende Beispiel zeigt, wie ein Account mit einem Alternativschlüssel aktualisiert wird, der für die Spalte accountnumber (Attribut) definiert ist.

Wichtig

Für die meisten Tabellen für Geschäftsdaten sind keine alternativen Schlüssel definiert. Diese Methode kann nur verwendet werden, wenn die Umgebung so konfiguriert ist, dass ein Alternativschlüssel für eine Tabelle definiert wird.

var accountNumberKey = new KeyAttributeCollection();
accountNumberKey.Add(new KeyValuePair<string, object>("accountnumber", "123456"));

Account exampleAccount = new Entity("account", accountNumberKey).ToEntity<Account>();
exampleAccount.Name = "New Account Name";
svc.Update(exampleAccount);

Weitere Informationen:

Aktualisieren und Löschen von Datensätzen in elastischen Tabellen

Wenn Sie Daten aus elastischen Tabellen, die in Partitionen gespeichert sind, aktualisieren oder löschen, geben Sie beim Zugriff auf diese Daten unbedingt den Partitionsschlüssel an. Weitere Informationen: Partitioning und horizontale Skalierung

Verwendung von Upsert

In der Regel müssen Sie in den Datenenintegrationsszenarien Daten in den Dataverse aus anderen Quellen erstellen oder aktualisieren. Dataverse hat ggf. bereits Datensätze mit dem gleichen eindeutigen Bezeichner, die möglicherweise ein Alternativschlüssel sind. Wenn eine Tabellenzeile vorhanden ist, möchten Sie sie aktualisieren. Sollte er nicht vorhanden sein, erstellen Sie ihn, damit die Daten, die hinzugefügt werden, mit den Quelldaten synchronisiert werden. Dieses Szenario ist erforderlich, wenn Sie upsert verwenden möchten.

Das folgende Beispiel nutzt ein UpsertRequest zweimal. Bei der erstmaligen Erstellung der Kontozeile und bei ihrer zweiten Aktualisierung, weil sie über einen Wert accountnumber verfügt und ein Alternativschlüssel vorhanden ist, der diese Spalte (Attribut) verwendet.

Bei beiden Aufrufen gibt die UpsertResponse.RecordCreated-Eigenschaft an, ob durch den Vorgang eine Zeile erstellt wurde oder nicht.

// This environment has an alternate key set for the accountnumber attribute.

//Instantiate account entity with accountnumber value
var account = new Entity("account", "accountnumber", "0003");
account["name"] = "New Account";

//Use Upsert the first time
UpsertRequest request1 = new UpsertRequest() {
Target = account
};

//The new entity is created
var response1 = (UpsertResponse)svc.Execute(request1);
Console.WriteLine("Record Created: {0}",response1.RecordCreated); //true

//Update the name of the existing account entity
account["name"] = "Updated Account";

//Use Upsert for the second time
UpsertRequest request2 = new UpsertRequest()
{
Target = account
};

//The existing entity is updated.
var response2 = (UpsertResponse)svc.Execute(request2);
Console.WriteLine("Record Created: {0}", response2.RecordCreated); //false

Weitere Informationen: Einen Datensatz mit Upsert einfügen oder aktualisieren

Delete

Die Iorganization.Service.Delete-Methode benötigt lediglich den logischen Namen der Tabelle und den eindeutigen Bezeichner. Unabhängig davon, ob Sie eine spät gebundene Enitätsklasse oder eine früh gebundene Entitätsklasse verwenden, können Sie die folgenden Syntax für einen Löschvorgang verwenden, indem Sie die Eigenschafteb Entity.LogicalName zbd Entity.ID übergeben.

svc.Delete(retrievedEntity.LogicalName, retrievedEntity.Id);

Alternativ können Sie auch dynamische Werte verwenden:

svc.Delete("account", new Guid("e5fa5509-2582-e811-a95e-000d3af40ae7"));

Wichtig

Löschvorgänge können kaskadierende Vorgänge initiieren, die untergeordnete Zeilen löschen können, um die Datenintegrität abhängig von der für Beziehungen in der Umgebung definierten Logik beizubehalten. Weitere Informationen: Tabellenbeziehungs-Verhalten

Die DeleteRequest-Klasse nutzen

Sie können die DeleteRequest-Klasse anstelle der IOrganizationService.Delete-Methode verwenden. Sie ist jedoch nur erforderlich, wenn Sie ein optimistisches Parallelitätsverhalten definieren möchten.

var retrievedEntity = new Entity("account")
{
    Id = new Guid("c81ffd82-cd82-e811-a95c-000d3af49bf8"),
    RowVersion = "986335"

};

var request = new DeleteRequest()
{
    Target = retrievedEntity.ToEntityReference(),
    ConcurrencyBehavior = ConcurrencyBehavior.IfRowVersionMatches
};

svc.Execute(request);

Verhalten der optimistischen Parallelität

Sie können das Verhalten der optimistischen Parallelität für den Vorgang angeben, indem Sie die ConcurrencyBehavior-Eigenschaft der UpdateRequest- oder DeleteRequest-Klassen festlegen.

Die Logik zum Aktualisieren oder Löschen der Zeile kann auf veralteten Daten basieren. Wenn die aktuellen Daten sich unterscheiden, da sie geändert wurden, seit sie abgerufen wurden, enthält die optimistische Parallelität eine Möglichkeit, ein Update oder einen Löschvorgang abzubrechen, sodass möglicherweise die Anfrage wiederholt werden kann, um die aktuellen Daten zu nutzen.

Um festzustellen, ob die Zeile geändert wurde, müssen Sie nicht alle Werte vergleichen. Sie können die Eigenschaft RowVersion verwenden, um zu sehen, ob sich an der Zeile etwas geändert hat.

Das folgende Beispiel wird nur erfolgreich ausgeführt, wenn:

  • Die RowVersion der Zeile in der Datenbank ist gleich 986323.
  • Die Kontotabelle für die optimistische Parallelität aktiviert ist (EntityMetadata.IsOptimisticConcurrencyEnabled-Eigenschaft ist true)
  • Die Eigenschaft RowVersion wird für die mit der Anforderung übergebene Zeile festgelegt.

Wenn RowVersion nicht übereinstimmt, tritt ein Fehler mit der The version of the existing record doesn't match the RowVersion property provided. Meldung auf.

var retrievedAccount = new Account()
{   
    Id = new Guid("a976763a-ba1c-e811-a954-000d3af451d6"), 
    RowVersion = "986323" 
};

var account = new Account();
account.Id = retrievedAccount.Id;
account.RowVersion = retrievedAccount.RowVersion;

// set attribute values
account.CreditOnHold = true;

//Update the account
var request = new UpdateRequest()
{ 
    Target = account,
    ConcurrencyBehavior = ConcurrencyBehavior.IfRowVersionMatches 
};

try
{
    svc.Execute(request);
}
catch (FaultException<OrganizationServiceFault> ex)
{
    switch (ex.Detail.ErrorCode)
    {
        case -2147088254: // ConcurrencyVersionMismatch 
        case -2147088253: // OptimisticConcurrencyNotEnabled 
            throw new InvalidOperationException(ex.Detail.Message);
        case -2147088243: // ConcurrencyVersionNotProvided
            throw new ArgumentNullException(ex.Detail.Message);
        default:
            throw ex;
    }
}

Weitere Informationen:

Vorgängerupdatenachrichten

Es gibt mehrere veraltete spezialisierte Nachrichten, die Aktualisierungsvorgänge ausführen. In früheren Versionen war es erforderlich, diese Nachrichten zu verwenden. Jetzt sollten die selben Vorgänge mithilfe von IOrganizationService.Update oder UpdateRequest-Klasse mit der IOrganizationService.Execute-Methode ausgeführt werden.

Veraltete Nachrichtenanforderung Zu aktualisierende(s) Attribut(e)
AssignRequest <Entität>.OwnerId
SetStateRequest <Entität>.StateCode
<Entität>.StatusCode
SetParentSystemUserRequest SystemUser.ParentSystemUserId
SetParentTeamRequest Team.BusinessUnitId
SetParentBusinessUnitRequest BusinessUnit.ParentBusinessUnitId
SetBusinessEquipmentRequest Arbeitsgerät.BusinessUnitId
SetBusinessSystemUserRequest SystemUser.BusinessUnitId

<Entität> verweist auf eine beliebige Entität, die dieses Attribut bereitstellt.

Wichtig

Wenn Sie die Spalte StateCode aktualisieren, ist es wichtig, dass Sie immer den gewünschten StatusCode festlegen.

StateCode und StatusCode haben abhängige Werte. Es kann mehrere gültige StatusCode-Werte für einen bestimmten StateCode-Wert geben, aber für jede StateCode-Spalte ist ein einziger DefaultStatus-Wert konfiguriert. Wenn Sie StateCode aktualisieren, ohne einen StatusCode anzugeben, wird der Standardstatuswert vom System festgelegt.

Wenn die Überwachung für die Tabelle und die StatusCode-Spalte aktiviert ist, wird der geänderte Wert für die StatusCode-Spalte nicht in den Überwachungsdaten erfasst, es sei denn, er wird im Aktualisierungsvorgang angegeben.

Weitere Informationen: Verhalten spezieller Vorgänge mithilfe Update

Siehe auch

Tabellenzeilen mit dem SDK für .NET erstellen
Abrufen einer Tabellenzeile über die SDK für .NET
Zuordnen und Aufheben der Zuordnung von Tabellenzeilen über das SDK für .NET