Share via


Datalagring

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019

Azure DevOps-tillägg kan lagra användarinställningar och komplexa datastrukturer direkt i Microsoft-tillhandahållen infrastruktur, vilket säkerställer att användarens data skyddas och säkerhetskopieras precis som andra organisations- och projektdata. Det innebär också att du som tilläggsprovider inte behöver konfigurera, hantera eller betala för datalagringstjänster från tredje part för enkla datalagringsbehov.

Det finns två metoder för att interagera med datalagringstjänsten: via REST-API:er eller via en klienttjänst som tillhandahålls av Microsoft, som är en del av VSS SDK. Vi rekommenderar tilläggsutvecklare att använda de tillhandahållna API:erna för klienttjänsten, eftersom de erbjuder en användarvänlig inkapsling av REST-API:erna.

Kommentar

Letar du efter REST-API:er för Azure DevOps? Se den senaste REST API-referensen för Azure DevOps.

Information om .NET-klientbibliotek finns i .NET-klientbibliotek för Azure DevOps.

Vad du kan lagra

Tjänsten är utformad för att du ska kunna lagra och hantera två olika typer av data:

  • Inställningar: enkla nyckel/värde-inställningar (till exempel användarinställningar)
  • Dokument: samlingar av liknande komplexa objekt (dokument)

En samling är som en indexerad container för dokument. Ett dokument är en JSON-blob som tillhör en samling. Förutom några få reserverade egenskapsnamn kontrollerar och hanterar du schemat för dessa dokument.

Så här kan du omfångsdata

Inställningar och dokumentsamlingar kan begränsas till antingen:

  • Projektsamling: delas av alla användare av projektsamlingen som tillägget är installerat på
  • Användare: en enskild användare i en projektsamling som tillägget är installerat på

Inställningar lagring

De två huvudsakliga metoderna för att hantera inställningar är getValue() och setValue():

  • getValue() accepterar en strängnyckel (tillsammans med andra alternativ som omfång) och returnerar en IPromise. Det lösta värdet för det här löftet är det värde som är associerat med den angivna nyckeln.
  • setValue() accepterar en strängnyckel, ett värde och andra alternativ, till exempel omfång, och returnerar en IPromise. Det lösta värdet för det här löftet är det uppdaterade värdet för inställningen.

Här är ett exempel på hur du anger ett värde:

        private async initializeState(): Promise<void> {
        await SDK.ready();
        const accessToken = await SDK.getAccessToken();
        const extDataService = await SDK.getService<IExtensionDataService>(CommonServiceIds.ExtensionDataService);
        this._dataManager = await extDataService.getExtensionDataManager(SDK.getExtensionContext().id, accessToken);

        this._dataManager.getValue<string>("test-id").then((data) => {
            this.setState({
                dataText: data,
                persistedText: data,
                ready: true
            });
        }, () => {
            this.setState({
                dataText: "",
                ready: true
            });
        });
    }

Här är ett exempel på hur du hämtar ett inställningsvärde:

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Get value in user scope
        dataService.getValue("userScopedKey", {scopeType: "User"}).then(function(value) {
            console.log("User scoped key value is " + value);
        });
    });

Om scopeType inte anges lagras inställningarna på projektsamlingsnivå och de är tillgängliga för alla användare i den projektsamlingen med hjälp av tillägget. Här är ett exempel på hur du anger ett inställningsvärde på projektsamlingsnivå:

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Set value (default is project collection scope)
        dataService.setValue("someKey", "abcd-efgh").then(function(value) {
            console.log("Key value is " + value);
        });
    });

Lagring av data (samlingar med dokument)

Om du vill hantera mer komplexa data utöver nyckel/värde-par kan du använda begreppet dokument för att köra CRUD-åtgärder på ditt tilläggs data. Ett dokument är en JSON-blob, utökad med två särskilda egenskaper: ID och __etag. Om de är avgörande för ett tilläggs datamodell kan ID:t vara användardefinierade, eller om de lämnas ospecificerade genererar systemet dem. Dessa ID:er måste vara unika i en specifik samling. Eftersom en samling refererar till ett visst omfång och en instans av ett tillägg innebär det att samma dokument-ID kan återanvändas i olika samlingar.

Följande dokumentåtgärder är tillgängliga:

  • Hämta ett dokument
  • Skapa ett dokument
  • Ange ett dokument (skapa eller uppdatera)
  • Uppdatera ett dokument
  • Ta bort ett dokument

Det finns också en enda åtgärd som kan utföras på en samling: Hämta alla dokument

Hämta ett dokument efter ID

Det är enkelt att hämta ett dokument från en samling med hjälp av dess identifierare, som i följande exempel:

    // Acquire data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Retrieve document by id
        dataService.getDocument("MyCollection", "MyDocumentId").then(function(doc) {
            // Assuming document has a property named foo
            console.log("Doc foo: " + doc.foo);
        });
    });

Den här åtgärden försöker hämta ett dokument med ID:t "MyDocumentId" från samlingen "MyCollection". I avsaknad av ett angivet omfång använder tjänsten som standard samlingen som är begränsad till hela instansen av det här tillägget. Om antingen den här samlingen eller ett dokument med det angivna ID:t inte finns returneras ett 404-fel som tillägget ska hantera. Det returnerade dokumentet är ett JSON-objekt som innehåller alla dess egenskaper, tillsammans med det särskilda ID och __etag egenskaper som används av datalagringstjänsten.

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Get document by id
        dataService.getDocument("MyCollection", "MyDocumentId").then(function(doc) {
            // Assuming document has a property named foo
            console.log("Doc foo: " + doc.foo);
        });
    });

Det här anropet försöker hämta ett dokument med ID:t "MyDocumentId" från samlingen "MyCollection". Eftersom det inte finns något omfång kommer samlingen som tjänsten använder att begränsas till standardvärdet för hela instansen av det här tillägget. Om den här samlingen inte finns eller om ett dokument med det ID:t inte finns returneras en 404 som tillägget ska hantera. Dokumentet som returneras är ett JSON-objekt som innehåller alla sina egna egenskaper, utöver det särskilda ID och __etag de egenskaper som används av datalagringstjänsten.

Skapa ett dokument

Om du vill skapa ett nytt dokument utför du ett anrop som i följande exempel:

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Prepare document first
        var newDoc = {
            fullScreen: false,
            screenWidth: 500
        };

        dataService.createDocument("MyCollection", newDoc).then(function(doc) {
            // Even if no ID was passed to createDocument, one gets generated
            console.log("Doc id: " + doc.id);
        });
    });

Om samlingen med det angivna namnet och omfånget ännu inte finns skapas den dynamiskt innan själva dokumentet skapas.

Om det angivna dokumentet innehåller en id egenskap används det värdet som det unika ID:t för dokumentet. Observera att angivet id bör vara begränsat till 50 tecken. Om fältet inte finns genereras ett GUID av tjänsten och ingår i dokumentet som returneras när löftet har lösts.

Om ett annat dokument i samlingen redan finns med samma ID som det som anges i dokumentet misslyckas åtgärden. Om det önskade beteendet är att skapa ett nytt dokument om ID:t inte finns, men ändra det befintliga dokumentet om det gör det, setDocument() bör metoden användas.

Ange ett dokument (uppdatera eller skapa)

Funktionen setDocument() utför en "upsert"-åtgärd – den ändrar ett befintligt dokument om dess ID finns och matchar ett dokument i samlingen. Om ID:t saknas eller inte motsvarar något dokument i samlingen läggs ett nytt dokument till i samlingen.

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Prepare document first
        var myDoc = {
            id: 1,
            fullScreen: false,
            screenWidth: 500
        };

        dataService.setDocument("MyCollection", myDoc).then(function(doc) {
            console.log("Doc id: " + doc.id);
        });
    });

Uppdatera ett dokument

Funktionen updateDocument kräver att dokumentet som ändras redan finns i samlingen. Ett undantag utlöses om inget ID har angetts eller om det angivna ID:t inte motsvarar något dokument i samlingen.

Här är ett exempel på hur uppdatering används:

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        var collection = "MyCollection";
        var docId = "1234-4567-8910";
        // Get document first
        dataService.getDocument(collection, docId, { scopeType: "User" }).then(function(doc) {
            // Update the document
            doc.name = "John Doe";
            dataService.updateDocument(collection, doc, { scopeType: "User" }).then(function(d) {
                // Check the new version
                console.log("Doc version: " + d.__etag);
            });
        });
    });

Ta bort ett dokument

Den här funktionen tar bort dokumentet med det angivna ID:t från den angivna samlingen. Om samlingen inte finns eller om dokumentet inte finns returneras 404.

Här är ett exempel på användning:

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        var docId = "1234-4567-8910";
        // Delete document
        dataService.deleteDocument("MyCollection", docId).then(function() {
            console.log("Doc deleted");
        });
    });

Hämta alla dokument i en samling

I följande exempel hämtas alla dokument från samlingen "MyCollection" med hjälp av datatjänsten och loggar sedan antalet dokument till konsolen:

    // Get data service
    SDK.getService(SDK.getContributionId()).then(function(dataService) {
        // Get all document under the collection
        dataService.getDocuments("MyCollection").then(function(docs) {
            console.log("There are " + docs.length + " in the collection.");
        });
    });

Det här anropet hämtar alla dokument i en begränsad samling med en gräns på 100 000 dokument. Om samlingen inte finns returnerar den ett 404-fel.

Avancerad

Så här lagras inställningarna

Det här anropet setDocument kapslar in klientmetoden och ger den flera datadelar. Som tidigare nämnts sparas inställningarna internt som dokument. Därför genereras ett grundläggande dokument dynamiskt, där dokumentets ID är nyckeln som anges i setValue() metoden. Dokumentet har ytterligare två egenskaper. Egenskapen value innehåller värdet som skickades till metoden och egenskapen revision är inställd på -1. Även om egenskapen revision beskrivs mer i avsnittet "Arbeta med dokument" innebär inställningen revision i dokumentet att -1 vi inte bryr oss om versionshantering av det här inställningsdokumentet i samband med inställningar.

Eftersom inställningarna lagras som dokument måste vi ange ett samlingsnamn som anger var dokumentet ska lagras. För att hålla det enkelt är samlingsnamnet alltid det speciella namnet $settingsnär du arbetar medgetValue()setValue()/metoderna. Föregående anrop utfärdar en PUT-begäran vid följande slutpunkt:

GET _apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extensionName}/Data/Scopes/User/Me/Collections/%24settings/Documents

Nyttolasten för begäran är som i följande exempel:

{
                "id": "myKey",
                "__etag": -1,
                "value": "myValue"
}

REST API:er

Förutsatt att det här kodfragmentet körs när värdet har angetts bör du se ett aviseringsmeddelande som innehåller texten "Värdet är myValue". getValue-metoden är återigen en omslutning runt REST-API:erna och skickar en GET-begäran till följande slutpunkt:

GET _apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extensionName}/Data/Scopes/User/Me/Collections/%24settings/Documents/myKey

Etags

Fältet __etag används av datalagringstjänsten för hantering av samtidighet i dokument. Innan en uppdatering sparas verifierar tjänsten att det __etag lagrade dokumentet matchar det __etag uppdaterade dokumentet. Om de matchar __etag ökas det och det uppdaterade dokumentet returneras till anroparen. Om de inte matchar anger det att dokumentet som ska uppdateras är inaktuellt och ett undantag genereras. Tilläggsskrivaren ansvarar för att hantera det här undantaget på ett korrekt sätt, antingen genom att hämta det senaste __etag dokumentet, slå samman ändringarna och försöka uppdatera igen eller genom att meddela användaren.

För vissa typer av dokument kanske den samtidighetsnivå som tillhandahålls inte är nödvändig och en modell för sista-i-vinner kan vara lämpligare. I sådana fall, när du redigerar dokumentet, anger du -1 som __etag värde för att beteckna den här funktionen. Den tidigare nämnda inställningstjänsten använder den här modellen för att lagra inställningar och inställningar.