Magazyn danych
Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019
Rozszerzenia usługi Azure DevOps mogą przechowywać preferencje użytkownika i złożone struktury danych bezpośrednio w infrastrukturze udostępnionej przez firmę Microsoft, co zapewnia bezpieczeństwo danych użytkownika i tworzenie kopii zapasowych, podobnie jak inne dane organizacji i projektu. Oznacza to również, że w przypadku prostych potrzeb związanych z magazynem danych, jako dostawcy rozszerzeń, nie trzeba konfigurować usług magazynu danych innych firm ani zarządzać nimi.
Istnieją dwie metody angażowania się w usługę magazynu danych: za pośrednictwem interfejsów API REST lub za pośrednictwem usługi klienta udostępnianej przez firmę Microsoft, która jest częścią zestawu VSS SDK. Zalecamy deweloperom rozszerzeń korzystanie z udostępnionych interfejsów API usługi klienta, ponieważ oferują one przyjazną dla użytkownika hermetyzację interfejsów API REST.
Uwaga
Szukasz interfejsów API REST usługi Azure DevOps? Zobacz najnowszą dokumentację interfejsu API REST usługi Azure DevOps.
Aby uzyskać informacje o bibliotekach klienta platformy .NET, zobacz Biblioteki klienta platformy .NET dla usługi Azure DevOps.
Co można przechowywać
Usługa została zaprojektowana tak, aby umożliwiała przechowywanie dwóch różnych typów danych i zarządzanie nimi:
- Ustawienia: proste ustawienia klucz-wartość (takie jak preferencje użytkownika)
- Dokumenty: kolekcje podobnych złożonych obiektów (dokumentów)
Kolekcja jest kontenerem indeksowanym dla dokumentów. Dokument jest obiektem blob JSON należącym do kolekcji. Poza kilkoma nazwami zastrzeżonych właściwości można kontrolować schemat tych dokumentów i zarządzać nim.
Jak można ograniczyć zakres danych
Ustawienia i kolekcje dokumentów mogą być ograniczone do następujących elementów:
- Kolekcja projektów: współużytkowana przez wszystkich użytkowników kolekcji projektów, do której zainstalowano rozszerzenie
- Użytkownik: pojedynczy użytkownik kolekcji projektu, do której zainstalowano rozszerzenie
magazyn Ustawienia
Dwie główne metody zarządzania ustawieniami to getValue()
i setValue()
:
getValue()
Akceptuje klucz ciągu (wraz z innymi opcjami, takimi jak zakres) i zwraca wartość IPromise. Rozpoznana wartość tej obietnicy to wartość skojarzona z podanym kluczem.setValue()
Akceptuje klucz ciągu, wartość i inne opcje, takie jak zakres, i zwraca wartość IPromise. Rozpoznana wartość tej obietnicy to zaktualizowana wartość ustawienia.
Oto przykład ustawiania wartości:
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
});
});
}
Oto przykład pobierania wartości ustawienia:
// 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);
});
});
Jeśli scopeType
nie zostanie określony, ustawienia są przechowywane na poziomie kolekcji projektów i są dostępne dla wszystkich użytkowników w tej kolekcji projektów przy użyciu rozszerzenia.
Oto przykład ustawiania wartości ustawienia na poziomie kolekcji projektów:
// 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);
});
});
Magazyn danych (kolekcji dokumentów)
Aby obsłużyć bardziej złożone dane poza pary klucz-wartość, możesz użyć koncepcji dokumentów do wykonywania operacji CRUD na danych rozszerzenia. Dokument jest obiektem blob JSON, rozszerzonym o dwie właściwości specjalne: ID i __etag
. Jeśli mają kluczowe znaczenie dla modelu danych rozszerzenia, identyfikatory mogą być zdefiniowane przez użytkownika lub jeśli nie zostały określone, system je generuje. Te identyfikatory muszą być unikatowe w ramach określonej kolekcji. Ponieważ kolekcja odwołuje się do określonego zakresu i wystąpienia rozszerzenia, oznacza to, że ten sam identyfikator dokumentu może być ponownie używany w różnych kolekcjach.
Dostępne są następujące operacje dokumentu:
- Pobieranie dokumentu
- Tworzenie dokumentu
- Ustawianie dokumentu (tworzenie lub aktualizowanie)
- Aktualizowanie dokumentu
- Usuwanie dokumentu
Istnieje również jedna operacja, którą można wykonać w kolekcji: Pobieranie wszystkich dokumentów
Pobieranie dokumentu według identyfikatora
Uzyskiwanie dokumentu z kolekcji przy użyciu jego identyfikatora jest proste, jak w poniższym przykładzie:
// 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);
});
});
Ta operacja próbuje pobrać dokument o identyfikatorze "MyDocumentId" z kolekcji "MyCollection". W przypadku braku podanego zakresu usługa domyślnie używa kolekcji w zakresie całego wystąpienia tego rozszerzenia. Jeśli ta kolekcja lub dokument o określonym identyfikatorze nie istnieje, zwracany jest błąd 404, który powinien obsługiwać rozszerzenie. Zwrócony dokument jest obiektem JSON zawierającym wszystkie jego właściwości wraz ze specjalnym identyfikatorem i __etag
właściwościami używanymi przez usługę magazynu danych.
// 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);
});
});
To wywołanie próbuje pobrać dokument o identyfikatorze "MyDocumentId" z kolekcji "MyCollection". Ponieważ nie podano zakresu, kolekcja używana przez usługę jest określana jako domyślna dla całego wystąpienia tego rozszerzenia. Jeśli ta kolekcja nie istnieje lub dokument o tym identyfikatorze nie istnieje, zwracany jest numer 404, który powinien obsłużyć rozszerzenie. Zwracany dokument jest obiektem JSON zawierającym wszystkie jego właściwości, oprócz specjalnego identyfikatora i __etag
właściwości używanych przez usługę magazynu danych.
Tworzenie dokumentu
Aby utworzyć nowy dokument, wykonaj wywołanie podobne do następującego przykładu:
// 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);
});
});
Jeśli kolekcja o podanej nazwie i zakresie nie istnieje, zostanie utworzona dynamicznie przed utworzeniem samego dokumentu.
Jeśli podany dokument zawiera id
właściwość, ta wartość zostanie użyta jako unikatowy identyfikator dokumentu. Należy pamiętać, że podana wartość id
powinna być ograniczona do 50 znaków. Jeśli to pole nie istnieje, identyfikator GUID zostanie wygenerowany przez usługę i uwzględniony w dokumencie zwróconym po rozwiązaniu obietnicy.
Jeśli inny dokument w kolekcji już istnieje o tym samym identyfikatorze co podany w dokumencie, operacja kończy się niepowodzeniem. Jeśli żądane zachowanie jest tworzone nowy dokument, jeśli identyfikator nie istnieje, ale zmodyfikuj istniejący dokument, jeśli tak, setDocument()
należy użyć metody.
Ustawianie dokumentu (aktualizowanie lub tworzenie)
Funkcja setDocument()
wykonuje operację "upsert" — modyfikuje istniejący dokument, jeśli jego identyfikator jest obecny i pasuje do dokumentu w kolekcji. Jeśli identyfikator jest nieobecny lub nie odpowiada żadnemu dokumentowi w kolekcji, nowy dokument zostanie dodany do kolekcji.
// 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);
});
});
Aktualizowanie dokumentu
Funkcja updateDocument
wymaga, aby zmieniany dokument znajdował się już w kolekcji. Wyjątek jest zgłaszany, jeśli nie podano żadnego identyfikatora lub jeśli podany identyfikator nie odpowiada żadnemu dokumentowi w kolekcji.
Oto przykład użycia aktualizacji:
// 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);
});
});
});
Usuwanie dokumentu
Ta funkcja usuwa dokument z podanym identyfikatorem z udostępnionej kolekcji. Jeśli kolekcja nie istnieje lub dokument nie istnieje, zwracany jest błąd 404.
Oto przykładowe użycie:
// 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");
});
});
Pobieranie wszystkich dokumentów w kolekcji
Poniższy przykład pobiera wszystkie dokumenty z kolekcji "MyCollection" przy użyciu usługi danych, a następnie rejestruje liczbę dokumentów w konsoli:
// 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.");
});
});
To wywołanie pobiera wszystkie dokumenty w kolekcji o określonym zakresie z limitem 100 000 dokumentów. Jeśli kolekcja nie istnieje, zwraca błąd 404.
Zaawansowani
Jak ustawienia są przechowywane
To wywołanie hermetyzuje metodę setDocument
klienta, podając ją przy użyciu wielu fragmentów danych. Jak wspomniano wcześniej, ustawienia są zapisywane wewnętrznie jako dokumenty. W związku z tym podstawowy dokument jest generowany dynamicznie, gdzie identyfikator dokumentu jest kluczem podanym w metodzie setValue()
. Dokument ma jeszcze dwie właściwości. Właściwość value
przechowuje wartość przekazaną do metody, a revision
właściwość jest ustawiona na -1
wartość . revision
Chociaż właściwość jest bardziej rozbudowana w sekcji "Praca z dokumentami", w kontekście ustawień ustawienie na revision
-1
wartość w dokumencie oznacza, że nie zajmujemy się przechowywaniem wersji tego dokumentu ustawień.
Ponieważ ustawienia są przechowywane jako dokumenty, musimy podać nazwę kolekcji wskazującą miejsce przechowywania dokumentu. Aby zachować prostotę, podczas pracy z metodami setValue()
/getValue()
nazwa kolekcji jest zawsze nazwą specjalną .$settings
Poprzednie wywołanie wystawia żądanie PUT w następującym punkcie końcowym:
GET _apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extensionName}/Data/Scopes/User/Me/Collections/%24settings/Documents
Ładunek żądania jest podobny do następującego przykładu:
{
"id": "myKey",
"__etag": -1,
"value": "myValue"
}
Interfejsy API REST
Zakładając, że ten fragment kodu jest wykonywany po ustawieniu wartości, powinien zostać wyświetlony komunikat alertu zawierający tekst "Wartość jest myValue". Metoda getValue jest ponownie otoką interfejsów API REST, wysyłając żądanie GET do następującego punktu końcowego:
GET _apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extensionName}/Data/Scopes/User/Me/Collections/%24settings/Documents/myKey
tagi etag
Pole __etag
jest używane przez usługę magazynu danych na potrzeby zarządzania współbieżnością dokumentów. Przed zapisaniem aktualizacji usługa sprawdza, czy __etag
aktualnie przechowywany dokument jest zgodny ze __etag
zaktualizowanym dokumentem. Jeśli są one zgodne, __etag
element jest zwiększany, a zaktualizowany dokument zostanie zwrócony do elementu wywołującego. Jeśli nie są one zgodne, oznacza to, że dokument do zaktualizowania jest nieaktualny i zgłaszany jest wyjątek. Składnik zapisywania rozszerzeń jest odpowiedzialny za obsługę tego wyjątku w sposób bezproblemowy, przez pobranie najnowszej wersji __etag
dokumentu, scalenie zmian i ponowienie próby aktualizacji lub powiadomienie użytkownika.
W przypadku niektórych typów dokumentów poziom podanej współbieżności może nie być konieczny, a model last-in-wins może być bardziej odpowiedni. W takich przypadkach podczas edytowania dokumentu wprowadź wartość -1 jako __etag
wartość, aby oznaczyć tę funkcję. Wcześniej wymieniona usługa ustawień używa tego modelu do przechowywania ustawień i preferencji.