Dela via


Uppgradera till Azure Search .NET SDK version 1.1

Om du använder version 1.0.2-preview eller äldre av Azure Search .NET SDK hjälper den här artikeln dig att uppgradera ditt program så att det använder version 1.1.

En mer allmän genomgång av SDK inklusive exempel finns i Så här använder du Azure Search från ett .NET-program.

Anteckning

När du har uppgraderat till version 1.1 eller om du redan använder en version mellan 1.1 och 2.0-preview bör du uppgradera till version 3. Anvisningar finns i Uppgradera till Azure Search .NET SDK version 3 .

Uppdatera först NuGet-referensen för Microsoft.Azure.Search att antingen använda NuGet Package Manager-konsolen eller genom att högerklicka på dina projektreferenser och välja "Hantera NuGet-paket..." i Visual Studio.

När NuGet har laddat ned de nya paketen och deras beroenden återskapar du projektet.

Om du tidigare använde version 1.0.0-preview, 1.0.1-preview eller 1.0.2-preview bör versionen lyckas och du är redo!

Om du tidigare använde version 0.13.0-preview eller äldre bör du se build-fel som följande:

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?)

Nästa steg är att åtgärda byggfelen en i taget. De flesta kräver att vissa klass- och metodnamn ändras som har bytt namn i SDK:et. Listan över icke-bakåtkompatibla ändringar i version 1.1 innehåller en lista över dessa namnändringar.

Om du använder anpassade klasser för att modellera dina dokument, och dessa klasser har egenskaper för primitiva typer som inte kan ha null-värde (till exempel int eller bool i C#), finns det en felkorrigering i 1.1-versionen av SDK som du bör känna till. Mer information finns i Felkorrigeringar i version 1.1 .

När du har åtgärdat eventuella byggfel kan du slutligen göra ändringar i ditt program för att dra nytta av nya funktioner om du vill.

Lista över icke-bakåtkompatibla ändringar i version 1.1

Följande lista sorteras efter sannolikheten att ändringen påverkar programkoden.

IndexBatch- och IndexAction-ändringar

IndexBatch.Create har bytt namn till IndexBatch.New och har inte längre något params argument. Du kan använda IndexBatch.New för batchar som blandar olika typer av åtgärder (sammanslagningar, borttagningar osv.). Dessutom finns det nya statiska metoder för att skapa batchar där alla åtgärder är desamma: Delete, Merge, MergeOrUploadoch Upload.

IndexAction har inte längre offentliga konstruktorer och dess egenskaper är nu oföränderliga. Du bör använda de nya statiska metoderna för att skapa åtgärder för olika syften: Delete, Merge, MergeOrUploadoch Upload. IndexAction.Create har tagits bort. Om du använde överbelastningen som bara tar ett dokument ska du använda Upload i stället.

Exempel

Om koden ser ut så här:

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

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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

Om du vill kan du förenkla det ytterligare så här:

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

IndexBatchException-ändringar

Egenskapen IndexBatchException.IndexResponse har bytt namn till IndexingResultsoch dess typ är nu IList<IndexingResult>.

Exempel

Om koden ser ut så här:

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)));
}

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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)));
}

Ändringar av åtgärdsmetod

Varje åtgärd i Azure Search .NET SDK exponeras som en uppsättning metodöverlagringar för synkrona och asynkrona anropare. Signaturer och faktorering för dessa metodöverlagringar har ändrats i version 1.1.

Åtgärden "Hämta indexstatistik" i äldre versioner av SDK exponerade till exempel dessa signaturer:

Följande gäller i IIndexOperations:

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

Följande gäller i 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);

Metodsignaturerna för samma åtgärd i version 1.1 ser ut så här:

Följande gäller i 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));

Följande gäller i 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));

Från och med version 1.1 organiserar Azure Search .NET SDK åtgärdsmetoder på olika sätt:

  • Valfria parametrar modelleras nu som standardparametrar i stället för ytterligare metodöverlagringar. Detta minskar antalet metodöverbelastningar, ibland dramatiskt.
  • Tilläggsmetoderna döljer nu mycket av den överflödiga informationen om HTTP från anroparen. Till exempel returnerade äldre versioner av SDK ett svarsobjekt med en HTTP-statuskod, som du ofta inte behövde kontrollera eftersom åtgärdsmetoderna genererar CloudException statuskod som indikerar ett fel. De nya tilläggsmetoderna returnerar bara modellobjekt, vilket gör att du slipper packa upp dem i koden.
  • På motsvarande sätt exponerar kärngränssnitten nu metoder som ger dig mer kontroll på HTTP-nivå om du behöver det. Du kan nu skicka in anpassade HTTP-huvuden som ska inkluderas i begäranden, och den nya AzureOperationResponse<T> returtypen ger dig direkt åtkomst till HttpRequestMessage och HttpResponseMessage för åtgärden. AzureOperationResponse definieras i Microsoft.Rest.Azure namnområdet och ersätter Hyak.Common.OperationResponse.

Ändringar i ScoringParameters

En ny klass med namnet ScoringParameter har lagts till i den senaste SDK:n för att göra det enklare att ange parametrar för bedömningsprofiler i en sökfråga. ScoringProfiles Tidigare skrevs egenskapen för SearchParameters klassen som IList<string>; Nu skrivs den som IList<ScoringParameter>.

Exempel

Om koden ser ut så här:

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

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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))
    };

Modellklassändringar

På grund av signaturändringarna som beskrivs i Åtgärdsmetodändringar har många klasser i Microsoft.Azure.Search.Models namnområdet bytt namn eller tagits bort. Exempel:

  • IndexDefinitionResponse har ersatts av AzureOperationResponse<Index>
  • DocumentSearchResponse har bytt namn till DocumentSearchResult
  • IndexResult har bytt namn till IndexingResult
  • Documents.Count() returnerar nu en long med antalet dokument i stället för en DocumentCountResponse
  • IndexGetStatisticsResponse har bytt namn till IndexGetStatisticsResult
  • IndexListResponse har bytt namn till IndexListResult

Sammanfattnings nog OperationResponsehar -härledda klasser som endast fanns för att omsluta ett modellobjekt tagits bort. De återstående klasserna har fått sitt suffix ändrat från Response till Result.

Exempel

Om koden ser ut så här:

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;

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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;

Svarsklasser och IEnumerable

En ytterligare ändring som kan påverka din kod är att svarsklasser som innehåller samlingar inte längre implementerar IEnumerable<T>. I stället kan du komma åt samlingsegenskapen direkt. Om koden till exempel ser ut så här:

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

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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

Specialfall för webbprogram

Om du har ett webbprogram som serialiseras DocumentSearchResponse direkt för att skicka sökresultat till webbläsaren måste du ändra koden, annars serialiseras resultaten inte korrekt. Om koden till exempel ser ut så här:

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)
    };
}

Du kan ändra det genom att hämta .Results egenskapen för söksvaret för att åtgärda sökresultatåtergivningen:

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
    };
}

Du måste leta efter sådana fall i din kod själv; Kompilatorn varnar dig inte eftersom JsonResult.Data är av typen object.

CloudException-ändringar

Klassen CloudException har flyttats från Hyak.Common namnområdet till Microsoft.Rest.Azure namnområdet. Dessutom har dess Error egenskap bytt namn till Body.

SearchServiceClient- och SearchIndexClient-ändringar

Egenskapens Credentials typ har ändrats från SearchCredentials till dess basklass, ServiceClientCredentials. Om du behöver åtkomst SearchCredentials till för en SearchIndexClient eller SearchServiceClientanvänder du den nya SearchCredentials egenskapen.

I äldre versioner av SDK SearchServiceClient och SearchIndexClient hade konstruktorer som tog en HttpClient parameter. Dessa har ersatts med konstruktorer som tar en HttpClientHandler och en matris med DelegatingHandler objekt. Detta gör det enklare att installera anpassade hanterare för att förbearbeta HTTP-begäranden om det behövs.

Slutligen har konstruktorerna som tog en Uri och SearchCredentials ändrats. Om du till exempel har kod som ser ut så här:

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

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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

Observera också att typen av parameter för autentiseringsuppgifter har ändrats till ServiceClientCredentials. Det här kommer sannolikt inte att påverka koden eftersom SearchCredentials den härleds från ServiceClientCredentials.

Skicka ett begärande-ID

I äldre versioner av SDK:n kan du ange ett begärande-ID för SearchServiceClient eller SearchIndexClient och det skulle inkluderas i varje begäran till REST-API:et. Detta är användbart för felsökning av problem med söktjänsten om du behöver kontakta supporten. Det är dock mer användbart att ange ett unikt begärande-ID för varje åtgärd i stället för att använda samma ID för alla åtgärder. Därför har metoderna SearchServiceClient för SetClientRequestId och SearchIndexClient tagits bort. I stället kan du skicka ett begärande-ID till varje åtgärdsmetod via den valfria SearchRequestOptions parametern .

Anteckning

I en framtida version av SDK lägger vi till en ny mekanism för att ange ett begärande-ID globalt på klientobjekten som överensstämmer med den metod som används av andra Azure-SDK:er.

Exempel

Om du har kod som ser ut så här:

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

Du kan ändra det till detta för att åtgärda eventuella byggfel:

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

Ändringar av gränssnittsnamn

Gränssnittsnamnen för åtgärdsgruppen har ändrats så att de överensstämmer med deras motsvarande egenskapsnamn:

  • Typen av ISearchServiceClient.Indexes har bytt namn från IIndexOperations till IIndexesOperations.
  • Typen av ISearchServiceClient.Indexers har bytt namn från IIndexerOperations till IIndexersOperations.
  • Typen av ISearchServiceClient.DataSources har bytt namn från IDataSourceOperations till IDataSourcesOperations.
  • Typen av ISearchIndexClient.Documents har bytt namn från IDocumentOperations till IDocumentsOperations.

Den här ändringen kommer sannolikt inte att påverka koden om du inte har skapat modeller av dessa gränssnitt i testsyfte.

Felkorrigeringar i version 1.1

Det uppstod en bugg i äldre versioner av Azure Search .NET SDK som rör serialisering av anpassade modellklasser. Felet kan inträffa om du har skapat en anpassad modellklass med en egenskap av en värdetyp som inte kan ha värdet null.

Steg för att återskapa

Skapa en anpassad modellklass med en egenskap av värdetypen som inte kan ha värdet null. Lägg till exempel till en offentlig UnitCount egenskap av typen int i stället för int?.

Om du indexar ett dokument med standardvärdet för den typen (till exempel 0 för int) blir fältet null i Azure Search. Om du sedan söker efter dokumentet utlöser anropet Search ett klagomål om att det inte kan konverteras null till int.JsonSerializationException

Filter kanske inte heller fungerar som förväntat eftersom null skrevs till indexet i stället för det avsedda värdet.

Åtgärda information

Vi har åtgärdat det här problemet i version 1.1 av SDK. Om du nu har en modellklass som den här:

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

    public int IntValue { get; set; }
}

och du anger IntValue till 0, det värdet är nu korrekt serialiserat som 0 på kabeln och lagras som 0 i indexet. Rund tripping fungerar också som förväntat.

Det finns ett potentiellt problem att vara medveten om med den här metoden: Om du använder en modelltyp med en egenskap som inte kan ha värdet null måste du garantera att inga dokument i indexet innehåller ett null-värde för motsvarande fält. Varken SDK:n eller REST-API:et för Azure Search hjälper dig att framtvinga detta.

Detta är inte bara ett hypotetiskt problem. Tänk dig ett scenario där du lägger till ett nytt fält till ett befintligt index som är av typen Edm.Int32. När du har uppdaterat indexdefinitionen har alla dokument ett null-värde för det nya fältet (eftersom alla typer kan vara null i Azure Search). Om du sedan använder en modellklass med en icke-nullbar int-egenskap för det fältet returneras ett JsonSerializationException som detta när du försöker hämta dokument:

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

Därför rekommenderar vi fortfarande att du använder typer som kan ha värdet null i dina modellklasser som bästa praxis.

Mer information om felet och korrigeringen finns i det här problemet på GitHub.