Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
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 / Notatka
Czy szukasz interfejsów REST API 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
Zakres ustawień i kolekcji dokumentów można ograniczyć 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 ustawień
Dwie główne metody zarządzania ustawieniami to getValue() i setValue():
-
getValue()Akceptuje ciągowy klucz (wraz z innymi opcjami, takimi jak zakres) i zwraca IPromise. Ustalona wartość tej obietnicy to wartość powiązana z podanym kluczem. -
setValue()Przyjmuje ciąg znaków jako klucz, wartość oraz inne opcje, takie jak zakres, i zwraca 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ługiwać bardziej złożone dane niż pary klucz-wartość, możesz wykorzystać koncepcję dokumentów do wykonywania operacji CRUD na danych swojego 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
Pobierz dokument po identyfikatorze
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 określonego zakresu, usługa domyślnie używa kolekcji dotyczącej 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 polega na utworzeniu nowego dokumentu, jeśli identyfikator nie istnieje, ale modyfikowaniu istniejącego dokumentu, jeśli już istnieje, należy użyć metody setDocument().
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");
});
});
Pobierz wszystkie dokumenty z 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.
Zaawansowany
Jak ustawienia są przechowywane
To wywołanie hermetyzuje metodę setDocument klienta, dostarczając jej 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 właściwość revision jest ustawiona na -1. Chociaż właściwość jest bardziej szczegółowo omówiona w sekcji "Praca z dokumentami", w kontekście ustawień ustawienie revision na revision w dokumencie oznacza, że nie zajmujemy się wersjonowaniem 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 programowania aplikacji REST
Zakładając, że ten fragment kodu jest wykonywany po ustawieniu wartości, powinien zostać wyświetlony komunikat ostrzeżenia zawierający tekst "Wartość to myValue". Metoda getValue jest ponownie warstwą interfejsów API REST, podając żądanie GET do następującego końcowego punktu dostępu:
GET _apis/ExtensionManagement/InstalledExtensions/{publisherName}/{extensionName}/Data/Scopes/User/Me/Collections/%24settings/Documents/myKey
ETagi
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 jest inkrementowany, a zaktualizowany dokument zostanie zwrócony do wywołującego. Jeśli nie są one zgodne, oznacza to, że dokument do zaktualizowania jest nieaktualny i zgłaszany jest wyjątek. Piszący rozszerzenie jest odpowiedzialny za płynną obsługę tego wyjątku, poprzez pobranie najnowszej wersji __etag dokumentu, scalenie zmian i ponowne spróbowanie dokonania aktualizacji lub powiadomienie użytkownika.
W przypadku niektórych typów dokumentów poziom zapewnionej 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, aby wskazać tę funkcję. Wcześniej wymieniona usługa ustawień używa tego modelu do przechowywania ustawień i preferencji.