Udostępnij za pośrednictwem


Uaktualnianie do zestawu .NET SDK usługi Azure Search w wersji 1.1

Jeśli używasz wersji 1.0.2-preview lub starszej zestawu .NET SDK usługi Azure Search, ten artykuł pomoże Ci uaktualnić aplikację do korzystania z wersji 1.1.

Aby zapoznać się z bardziej ogólnym przewodnikiem po zestawie SDK, w tym przykładami, zobacz How to use Azure Search from a .NET Application (Jak używać usługi Azure Search z poziomu aplikacji .NET).

Uwaga

Po uaktualnieniu do wersji 1.1 lub jeśli używasz już wersji od 1.1 do 2.0 w wersji zapoznawczej, należy przeprowadzić uaktualnienie do wersji 3. Aby uzyskać instrukcje, zobacz Uaktualnianie do zestawu .NET SDK usługi Azure Search w wersji 3 .

Najpierw zaktualizuj odwołanie do NuGet przy Microsoft.Azure.Search użyciu konsoli NuGet Menedżer pakietów lub klikając prawym przyciskiem myszy odwołania do projektu i wybierając pozycję "Zarządzaj pakietami NuGet..." w Visual Studio.

Po NuGet pobrać nowe pakiety i ich zależności ponownie skompiluj projekt.

Jeśli wcześniej używano wersji 1.0.0-preview, 1.0.1-preview lub 1.0.2-preview, kompilacja powinna zakończyć się pomyślnie i wszystko będzie gotowe!

Jeśli wcześniej używano wersji 0.13.0-preview lub starszej, powinny zostać wyświetlone błędy kompilacji podobne do następujących:

Program.cs(137,56,137,62): error CS0117: 'Microsoft.Azure.Search.Models.IndexBatch' does not contain a definition for 'Create'
Program.cs(137,99,137,105): error CS0117: 'Microsoft.Azure.Search.Models.IndexAction' does not contain a definition for 'Create'
Program.cs(146,41,146,54): error CS1061: 'Microsoft.Azure.Search.IndexBatchException' does not contain a definition for 'IndexResponse' and no extension method 'IndexResponse' accepting a first argument of type 'Microsoft.Azure.Search.IndexBatchException' could be found (are you missing a using directive or an assembly reference?)
Program.cs(163,13,163,42): error CS0246: The type or namespace name 'DocumentSearchResponse' could not be found (are you missing a using directive or an assembly reference?)

Następnym krokiem jest naprawienie błędów kompilacji jeden po drugim. Większość będzie wymagać zmiany niektórych nazw klas i metod, które zostały zmienione w zestawie SDK. Lista zmian powodujących niezgodność w wersji 1.1 zawiera listę tych zmian nazw.

Jeśli używasz klas niestandardowych do modelowania dokumentów, a te klasy mają właściwości typów pierwotnych nienależących do wartości null (na przykład int lub bool w języku C#), w wersji 1.1 zestawu SDK należy pamiętać. Aby uzyskać więcej informacji, zobacz Poprawki błędów w wersji 1.1 .

Na koniec po usunięciu błędów kompilacji możesz wprowadzić zmiany w aplikacji, aby skorzystać z nowych funkcji, jeśli chcesz.

Lista zmian powodujących niezgodność w wersji 1.1

Poniższa lista jest uporządkowana według prawdopodobieństwa, że zmiana wpłynie na kod aplikacji.

Zmiany IndexBatch i IndexAction

IndexBatch.Create zmieniono nazwę na IndexBatch.New i nie ma już argumentu params . Można użyć IndexBatch.New dla partii, które mieszają różne typy akcji (scalania, usuwania itp.). Ponadto istnieją nowe metody statyczne do tworzenia partii, w których wszystkie akcje są takie same: Delete, , MergeMergeOrUploadi Upload.

IndexAction Nie ma już publicznych konstruktorów, a jego właściwości są teraz niezmienne. Należy użyć nowych metod statycznych do tworzenia akcji dla różnych celów: Delete, , MergeMergeOrUpload, i Upload. IndexAction.Create został usunięty. Jeśli użyto przeciążenia, które pobiera tylko dokument, pamiętaj, aby zamiast tego użyć Upload .

Przykład

Jeśli kod wygląda następująco:

var batch = IndexBatch.Create(documents.Select(doc => IndexAction.Create(doc)));
indexClient.Documents.Index(batch);

Możesz ją zmienić, aby naprawić błędy kompilacji:

var batch = IndexBatch.New(documents.Select(doc => IndexAction.Upload(doc)));
indexClient.Documents.Index(batch);

Jeśli chcesz, możesz jeszcze bardziej uprościć ten proces:

var batch = IndexBatch.Upload(documents);
indexClient.Documents.Index(batch);

Zmiany indexBatchException

Nazwa IndexBatchException.IndexResponse właściwości została zmieniona na IndexingResults, a jej typ to teraz IList<IndexingResult>.

Przykład

Jeśli kod wygląda następująco:

catch (IndexBatchException e)
{
    Console.WriteLine(
        "Failed to index some of the documents: {0}",
        String.Join(", ", e.IndexResponse.Results.Where(r => !r.Succeeded).Select(r => r.Key)));
}

Możesz ją zmienić, aby naprawić błędy kompilacji:

catch (IndexBatchException e)
{
    Console.WriteLine(
        "Failed to index some of the documents: {0}",
        String.Join(", ", e.IndexingResults.Where(r => !r.Succeeded).Select(r => r.Key)));
}

Zmiany metody operacji

Każda operacja w zestawie .NET SDK usługi Azure Search jest uwidaczniona jako zestaw przeciążeń metod synchronicznych i asynchronicznych. Podpisy i faktoring tych przeciążeń metody zmieniły się w wersji 1.1.

Na przykład operacja "Pobierz statystyki indeksu" w starszych wersjach zestawu SDK uwidoczniła następujące podpisy:

W pliku IIndexOperations:

// Asynchronous operation with all parameters
Task<IndexGetStatisticsResponse> GetStatisticsAsync(
    string indexName,
    CancellationToken cancellationToken);

W pliku IndexOperationsExtensions:

// Asynchronous operation with only required parameters
public static Task<IndexGetStatisticsResponse> GetStatisticsAsync(
    this IIndexOperations operations,
    string indexName);

// Synchronous operation with only required parameters
public static IndexGetStatisticsResponse GetStatistics(
    this IIndexOperations operations,
    string indexName);

Podpisy metody dla tej samej operacji w wersji 1.1 wyglądają następująco:

W pliku IIndexesOperations:

// Asynchronous operation with lower-level HTTP features exposed
Task<AzureOperationResponse<IndexGetStatisticsResult>> GetStatisticsWithHttpMessagesAsync(
    string indexName,
    SearchRequestOptions searchRequestOptions = default(SearchRequestOptions),
    Dictionary<string, List<string>> customHeaders = null,
    CancellationToken cancellationToken = default(CancellationToken));

W pliku IndexesOperationsExtensions:

// Simplified asynchronous operation
public static Task<IndexGetStatisticsResult> GetStatisticsAsync(
    this IIndexesOperations operations,
    string indexName,
    SearchRequestOptions searchRequestOptions = default(SearchRequestOptions),
    CancellationToken cancellationToken = default(CancellationToken));

// Simplified synchronous operation
public static IndexGetStatisticsResult GetStatistics(
    this IIndexesOperations operations,
    string indexName,
    SearchRequestOptions searchRequestOptions = default(SearchRequestOptions));

Począwszy od wersji 1.1, zestaw .NET SDK usługi Azure Search organizuje metody operacji inaczej:

  • Parametry opcjonalne są teraz modelowane jako parametry domyślne, a nie dodatkowe przeciążenia metody. Zmniejsza to liczbę przeciążeń metody, czasami dramatycznie.
  • Metody rozszerzenia ukrywają teraz wiele nadmiarowych szczegółów protokołu HTTP od obiektu wywołującego. Na przykład starsze wersje zestawu SDK zwróciły obiekt odpowiedzi z kodem stanu HTTP, którego często nie trzeba sprawdzać, ponieważ metody operacji zgłaszają CloudException dowolny kod stanu wskazujący błąd. Nowe metody rozszerzenia po prostu zwracają obiekty modelu, co pozwala zaoszczędzić problemy z koniecznością odpakowania ich w kodzie.
  • Z drugiej strony, podstawowe interfejsy teraz uwidaczniają metody, które zapewniają większą kontrolę na poziomie HTTP, jeśli jest to potrzebne. Teraz można przekazywać niestandardowe nagłówki HTTP, które mają być uwzględniane w żądaniach, a nowy AzureOperationResponse<T> typ zwracania zapewnia bezpośredni dostęp do elementów HttpRequestMessage i HttpResponseMessage dla operacji. AzureOperationResponse element jest zdefiniowany w Microsoft.Rest.Azure przestrzeni nazw i zastępuje wartość Hyak.Common.OperationResponse.

Zmiany parametrów oceniania

W najnowszym zestawie SDK dodano nową klasę o nazwie ScoringParameter , aby ułatwić udostępnianie parametrów profilom oceniania w zapytaniu wyszukiwania. ScoringProfiles Wcześniej właściwość SearchParameters klasy została wpisana jako IList<string>; Teraz jest on wpisany jako IList<ScoringParameter>.

Przykład

Jeśli kod wygląda następująco:

var sp = new SearchParameters();
sp.ScoringProfile = "jobsScoringFeatured";      // Use a scoring profile
sp.ScoringParameters = new[] { "featuredParam-featured", "mapCenterParam-" + lon + "," + lat };

Możesz ją zmienić, aby naprawić błędy kompilacji:

var sp = new SearchParameters();
sp.ScoringProfile = "jobsScoringFeatured";      // Use a scoring profile
sp.ScoringParameters =
    new[]
    {
        new ScoringParameter("featuredParam", new[] { "featured" }),
        new ScoringParameter("mapCenterParam", GeographyPoint.Create(lat, lon))
    };

Zmiany klas modelu

Ze względu na zmiany podpisu opisane w sekcji Zmiany metody operacji wiele klas w Microsoft.Azure.Search.Models przestrzeni nazw zostało zmienionych lub usuniętych. Przykład:

  • IndexDefinitionResponse został zastąpiony przez AzureOperationResponse<Index>
  • Zmieniono nazwę polecenia DocumentSearchResponse na DocumentSearchResult
  • Zmieniono nazwę polecenia IndexResult na IndexingResult
  • Documents.Count() teraz zwraca wartość long z liczbą dokumentów zamiast DocumentCountResponse
  • Zmieniono nazwę polecenia IndexGetStatisticsResponse na IndexGetStatisticsResult
  • Zmieniono nazwę polecenia IndexListResponse na IndexListResult

Podsumowując, OperationResponseklasy pochodne, które istniały tylko do opakowywania obiektu modelu, zostały usunięte. Pozostałe klasy zmieniły sufiks z Response na Result.

Przykład

Jeśli kod wygląda następująco:

IndexerGetStatusResponse statusResponse = null;

try
{
    statusResponse = _searchClient.Indexers.GetStatus(indexer.Name);
}
catch (Exception ex)
{
    Console.WriteLine("Error polling for indexer status: {0}", ex.Message);
    return;
}

IndexerExecutionResult lastResult = statusResponse.ExecutionInfo.LastResult;

Możesz ją zmienić, aby naprawić błędy kompilacji:

IndexerExecutionInfo status = null;

try
{
    status = _searchClient.Indexers.GetStatus(indexer.Name);
}
catch (Exception ex)
{
    Console.WriteLine("Error polling for indexer status: {0}", ex.Message);
    return;
}

IndexerExecutionResult lastResult = status.LastResult;

Klasy odpowiedzi i IEnumerable

Dodatkową zmianą, która może mieć wpływ na kod, jest to, że klasy odpowiedzi, które przechowują kolekcje, nie implementują już elementu IEnumerable<T>. Zamiast tego możesz bezpośrednio uzyskać dostęp do właściwości kolekcji. Jeśli na przykład kod wygląda następująco:

DocumentSearchResponse<Hotel> response = indexClient.Documents.Search<Hotel>(searchText, sp);
foreach (SearchResult<Hotel> result in response)
{
    Console.WriteLine(result.Document);
}

Możesz ją zmienić, aby naprawić błędy kompilacji:

DocumentSearchResult<Hotel> response = indexClient.Documents.Search<Hotel>(searchText, sp);
foreach (SearchResult<Hotel> result in response.Results)
{
    Console.WriteLine(result.Document);
}

Specjalny przypadek dla aplikacji internetowych

Jeśli masz aplikację internetową, która serializuje DocumentSearchResponse się bezpośrednio w celu wysyłania wyników wyszukiwania do przeglądarki, musisz zmienić kod lub wyniki nie będą serializować poprawnie. Jeśli na przykład kod wygląda następująco:

public ActionResult Search(string q = "")
{
    // If blank search, assume they want to search everything
    if (string.IsNullOrWhiteSpace(q))
        q = "*";

    return new JsonResult
    {
        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
        Data = _featuresSearch.Search(q)
    };
}

Możesz ją zmienić, uzyskując .Results właściwość odpowiedzi wyszukiwania, aby naprawić renderowanie wyników wyszukiwania:

public ActionResult Search(string q = "")
{
    // If blank search, assume they want to search everything
    if (string.IsNullOrWhiteSpace(q))
        q = "*";

    return new JsonResult
    {
        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
        Data = _featuresSearch.Search(q).Results
    };
}

W kodzie trzeba będzie samodzielnie wyszukać takie przypadki; Kompilator nie wyświetli ostrzeżenia , ponieważ JsonResult.Data jest typu object.

Zmiany cloudException

Klasa CloudException została przeniesiona Hyak.Common z przestrzeni nazw do Microsoft.Rest.Azure przestrzeni nazw. Ponadto jej Error właściwość została zmieniona na Body.

Zmiany elementu SearchServiceClient i SearchIndexClient

Typ Credentials właściwości zmienił się z SearchCredentials na jej klasę bazową . ServiceClientCredentials Jeśli musisz uzyskać dostęp SearchCredentials do obiektu SearchIndexClient lub SearchServiceClient, użyj nowej SearchCredentials właściwości.

W starszych wersjach zestawu SDK i SearchIndexClient miał konstruktory, SearchServiceClient które miały HttpClient parametr. Zostały one zastąpione konstruktorami, które przyjmują tablicę HttpClientHandlerDelegatingHandler obiektów i . Ułatwia to instalowanie niestandardowych procedur obsługi w celu wstępnego przetwarzania żądań HTTP w razie potrzeby.

Na koniec konstruktory, które miały Uri element i SearchCredentials uległy zmianie. Jeśli na przykład masz kod, który wygląda następująco:

var client =
    new SearchServiceClient(
        new SearchCredentials("abc123"),
        new Uri("http://myservice.search.windows.net"));

Możesz ją zmienić, aby naprawić błędy kompilacji:

var client =
    new SearchServiceClient(
        new Uri("http://myservice.search.windows.net"),
        new SearchCredentials("abc123"));

Należy również pamiętać, że typ parametru poświadczeń został zmieniony na ServiceClientCredentials. Jest to mało prawdopodobne, aby wpłynąć na kod, ponieważ SearchCredentials pochodzi z .ServiceClientCredentials

Przekazywanie identyfikatora żądania

W starszych wersjach zestawu SDK można ustawić identyfikator żądania dla SearchServiceClient elementu lub SearchIndexClient i będzie on uwzględniany w każdym żądaniu do interfejsu API REST. Jest to przydatne w przypadku rozwiązywania problemów z usługą wyszukiwania, jeśli musisz skontaktować się z pomocą techniczną. Jednak bardziej przydatne jest ustawienie unikatowego identyfikatora żądania dla każdej operacji, a nie użycie tego samego identyfikatora dla wszystkich operacji. Z tego powodu SetClientRequestId metody SearchServiceClient i SearchIndexClient zostały usunięte. Zamiast tego można przekazać identyfikator żądania do każdej metody operacji za pomocą opcjonalnego SearchRequestOptions parametru.

Uwaga

W przyszłej wersji zestawu SDK dodamy nowy mechanizm ustawiania identyfikatora żądania globalnie na obiektach klienta, które są zgodne z podejściem używanym przez inne zestawy SDK platformy Azure.

Przykład

Jeśli masz kod, który wygląda następująco:

client.SetClientRequestId(Guid.NewGuid());
...
long count = client.Documents.Count();

Możesz ją zmienić, aby naprawić błędy kompilacji:

long count = client.Documents.Count(new SearchRequestOptions(requestId: Guid.NewGuid()));

Zmiany nazwy interfejsu

Nazwy interfejsów grupy operacji zostały zmienione tak, aby były zgodne z odpowiednimi nazwami właściwości:

  • Nazwa typu ISearchServiceClient.Indexes została zmieniona z IIndexOperations na IIndexesOperations.
  • Nazwa typu ISearchServiceClient.Indexers została zmieniona z IIndexerOperations na IIndexersOperations.
  • Nazwa typu ISearchServiceClient.DataSources została zmieniona z IDataSourceOperations na IDataSourcesOperations.
  • Nazwa typu ISearchIndexClient.Documents została zmieniona z IDocumentOperations na IDocumentsOperations.

Ta zmiana prawdopodobnie nie wpłynie na kod, chyba że utworzono makiety tych interfejsów do celów testowych.

Poprawki błędów w wersji 1.1

W starszych wersjach zestawu .NET SDK usługi Azure Search wystąpił błąd związany z serializacji niestandardowych klas modelu. Usterka może wystąpić, jeśli utworzono niestandardową klasę modelu z właściwością typu wartości innej niż null.

Kroki odtwarzania

Utwórz niestandardową klasę modelu z właściwością typu wartości innej niż null. Na przykład dodaj właściwość publiczną UnitCount typu int zamiast int?.

Jeśli zaindeksujesz dokument z wartością domyślną tego typu (na przykład 0 dla int), pole będzie mieć wartość null w usłudze Azure Search. Jeśli następnie wyszukasz ten dokument, Search wywołanie zgłosi JsonSerializationException zgłoszenie, że nie będzie można przekonwertować null go na int.

Ponadto filtry mogą nie działać zgodnie z oczekiwaniami, ponieważ wartość null została zapisana w indeksie zamiast zamierzonej wartości.

Poprawka szczegółów

Rozwiązaliśmy ten problem w wersji 1.1 zestawu SDK. Teraz, jeśli masz klasę modelu w następujący sposób:

public class Model
{
    public string Key { get; set; }

    public int IntValue { get; set; }
}

i ustawiono IntValue wartość 0, ta wartość jest teraz poprawnie serializowana jako 0 w przewodzie i przechowywana jako 0 w indeksie. Zaokrąglanie działa również zgodnie z oczekiwaniami.

Istnieje jeden z potencjalnych problemów, o których należy pamiętać przy użyciu tego podejścia: jeśli używasz typu modelu z właściwością niepustą, musisz zagwarantować , że żadne dokumenty w indeksie nie zawierają wartości null dla odpowiedniego pola. Ani zestaw SDK, ani interfejs API REST usługi Azure Search nie pomogą Ci wymusić tego.

Nie jest to czysto hipotetyczny problem: wyobraź sobie scenariusz, w którym dodajesz nowe pole do istniejącego indeksu typu Edm.Int32. Po zaktualizowaniu definicji indeksu wszystkie dokumenty będą miały wartość null dla tego nowego pola (ponieważ wszystkie typy w usłudze Azure Search dopuszczają wartość null). Jeśli następnie dla tego pola użyjesz klasy modelu z właściwością int niedopuszczającą wartości null, podczas próby pobrania dokumentów otrzymasz wyjątek JsonSerializationException podobny do poniższego:

Error converting value {null} to type 'System.Int32'. Path 'IntValue'.

Z tego powodu nadal zalecamy używanie typów dopuszczających wartość null w klasach modelu jako najlepsze rozwiązanie.

Aby uzyskać więcej informacji na temat tej usterki i poprawki, zobacz ten problem w GitHub.