升級至 Azure 搜尋服務 .NET SDK 1.1 版

如果您使用 1.0.2 版或舊版 的 Azure 搜尋服務 .NET SDK,本文將協助您升級應用程式以使用 1.1 版。

如需 SDK 的更一般逐步解說,包括範例,請參閱 如何從 .NET 應用程式使用 Azure 搜尋服務。

備註

一旦您已升級至 1.1 版,或如果您已在使用從 1.1 到 2.0 預覽版之間(包括這些版本)的任何版本,您應該升級到第 3 版。 如需相關指示 ,請參閱升級至 Azure 搜尋服務 .NET SDK 第 3 版 。

首先,在 Visual Studio 中,使用 NuGet 套件管理員控制台或以滑鼠右鍵單擊專案參考,然後選取「管理 NuGet 套件...」來更新 Microsoft.Azure.Search 的 NuGet 參考。

一旦 NuGet 下載新的套件及其相依性,請重建您的專案。

如果您先前使用 1.0.0-preview、1.0.1-preview 或 1.0.2-preview 版本,組建應該會成功,且您已準備好進行!

如果您先前使用 0.13.0-preview 版或較舊版本,您應該會看到組建錯誤,如下所示:

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

下一個步驟是逐一修正建置錯誤。 大部分都需要變更 SDK 中已重新命名的一些類別和方法名稱。 1.1 版的重大變更清單 包含這些名稱變更的清單。

如果您使用自訂類別來為您的文件建模,而這些類別具有非空的基本類型屬性(例如 C# 中的 int 或 bool),請注意在 SDK 1.1 版中有一個錯誤修正。 如需詳細資訊 ,請參閱 1.1 版的錯誤修正 。

最後,修正任何建置錯誤之後,您可以變更應用程式,以視需要利用新功能。

1.1 版的重大變更清單

下列清單會依變更會影響應用程式程序代碼的可能性排序。

IndexBatch 和 IndexAction 變更

IndexBatch.Create 已重新命名為 IndexBatch.New ,且不再有 自 params 變數。 您可以 IndexBatch.New 用於混合不同類型的動作的批次(合併、刪除等)。 此外,還有新的靜態方法來建立批次,其中所有動作都相同: Delete、 Merge、 MergeOrUpload和 Upload。

IndexAction 不再有公用建構函式,而且其屬性現在不可變。 您應該使用新的靜態方法來建立不同用途的動作: Delete、 Merge、 MergeOrUpload和 Upload。 已移除 IndexAction.Create。 如果您使用了只接受文件的多載,請改為使用 Upload 。

範例

如果您的程式代碼看起來像這樣:

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

您可以將它變更為這個,以修正任何建置錯誤:

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

如有需要,您可以進一步將其簡化為:

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

IndexBatchException 變更

屬性 IndexBatchException.IndexResponse 已重新命名為 IndexingResults,而且其類型現在是 IList<IndexingResult>。

範例

如果您的程式代碼看起來像這樣:

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

您可以將它變更為這個,以修正任何建置錯誤:

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

作業方法變更

Azure 搜尋服務 .NET SDK 中的每個作業都會公開為同步和異步呼叫者的一組方法重載。 這些方法重載的簽名和重構已在 1.1 版中變更。

例如,舊版 SDK 中的「取得索引統計數據」作業會公開這些簽章:

在 IIndexOperations 中:

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

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

1.1 版中相同作業的方法簽章如下所示:

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

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

從 1.1 版開始,Azure 搜尋服務 .NET SDK 會以不同的方式組織作業方法:

  • 選擇性參數現在會模型化為預設參數,而不是其他方法多載。 這可顯著減少方法多載的數目, 而在某些情況下甚至能大幅減少。
  • 擴充方法現在會從呼叫端隱藏許多 HTTP 的額外詳細數據。 例如,舊版 SDK 傳回具有 HTTP 狀態代碼的回應物件,您通常不需要檢查,因為作業方法會針對指出錯誤的任何狀態代碼擲回 CloudException 。 新的擴充方法只會傳回模型物件,讓您不必在程式代碼中解除包裝它們。
  • 相反地,核心介面現在會公開方法,讓您在 HTTP 層級獲得更多控制權。如果您需要的話。 您現在可以傳入要包含在請求中的自定義 HTTP 標頭,而新的 AzureOperationResponse<T> 傳回類型可讓您直接存取 HttpRequestMessage 和 HttpResponseMessage 操作。 AzureOperationResponse 定義於命名空間中 Microsoft.Rest.Azure ,並取代 Hyak.Common.OperationResponse。

ScoringParameters 變更

已在最新的 SDK 中新增名為 ScoringParameter 的新類別,可讓您更輕鬆地在搜尋查詢中提供評分配置檔的參數。 先前 ScoringProfiles 類別 SearchParameters 的 屬性已輸入為 IList<string>;現在它會輸入為 IList<ScoringParameter>。

範例

如果您的程式代碼看起來像這樣:

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

您可以將它變更為這個,以修正任何建置錯誤:

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

模型類別變更

由於 Operation 方法變更中所述的簽章變更,命名空間中的 Microsoft.Azure.Search.Models 許多類別已重新命名或移除。 例如:

  • IndexDefinitionResponse 已由 AzureOperationResponse<Index> 取代
  • DocumentSearchResponse 已重新命名為 DocumentSearchResult
  • IndexResult 已重新命名為 IndexingResult
  • Documents.Count() 現在返回包含文檔數量的 long,而不是 DocumentCountResponse。
  • IndexGetStatisticsResponse 已重新命名為 IndexGetStatisticsResult
  • IndexListResponse 已重新命名為 IndexListResult

總結來說,OperationResponse只為了包裝模型物件而存在的衍生類別已經移除。 其餘類別的後綴已從 Response 變更為 Result。

範例

如果您的程式代碼看起來像這樣:

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;

您可以將它變更為這個,以修正任何建置錯誤:

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;

回應類別和 IEnumerable

可能會影響程式代碼的其他變更是保留集合的回應類別不再實作 IEnumerable<T>。 相反地,您可以直接存取集合屬性。 例如,如果您的程式代碼看起來像這樣:

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

您可以將它變更為這個,以修正任何建置錯誤:

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

Web 應用程式的特殊案例

如果您有直接串行化 DocumentSearchResponse 以將搜尋結果傳送至瀏覽器的 Web 應用程式,您必須變更程式代碼,否則結果將無法正確串行化。 例如,如果您的程式代碼看起來像這樣:

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 搜尋回應的 屬性來修正搜尋結果轉譯來變更它:

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

您必須自行在程式代碼中尋找這類案例; 編譯程式不會警告您 ,因為 JsonResult.Data 類型 object為 。

CloudException 變更

類別 CloudException 已從命名空間 Hyak.Common 移至命名空間 Microsoft.Rest.Azure。 此外,其 Error 屬性已重新命名為 Body。

SearchServiceClient 和 SearchIndexClient 的變更

屬性的類型Credentials已從 SearchCredentials 變更為其基類 。 ServiceClientCredentials 如果您需要存取某個 SearchIndexClient 的 SearchCredentials 或 SearchServiceClient,請使用新的 SearchCredentials 屬性。

在舊版的 SDK 中,SearchServiceClient 和 SearchIndexClient 配有可以接受 HttpClient 參數的建構函式。 這些已被取代為使用 HttpClientHandler 和 DelegatingHandler 物件陣列的建構函式。 這可讓您更輕鬆地視需要安裝自定義處理程式來預先處理 HTTP 要求。

最後,使用 Uri 和 SearchCredentials 的建構函式已經改變。 例如,如果您有如下所示的程序代碼:

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

您可以將它變更為這個,以修正任何建置錯誤:

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

請注意,認證參數的類型已變更為 ServiceClientCredentials。 這不太可能影響您的程式代碼,因為 SearchCredentials 衍生自 ServiceClientCredentials。

傳遞請求 ID

在舊版 SDK 中,您可以在 或 SearchIndexClient 上SearchServiceClient設定要求識別碼,並將它包含在 REST API 的每個要求中。 如果您需要連絡支持人員,這適用於針對搜尋服務的問題進行疑難解答。 不過,設定每個作業的唯一要求標識符,而不是對所有作業使用相同的標識碼會比較有用。 因此,SetClientRequestId 和 SearchServiceClient 的方法已被移除SearchIndexClient。 相反地,您可以透過選擇性 SearchRequestOptions 參數,將要求標識碼傳遞至每個作業方法。

備註

在未來的 SDK 版本中,我們將新增一個新的機制,以全域方式在用戶端對象上設定要求標識碼,這與其他 Azure SDK 所使用的方法一致。

範例

如果您有如下所示的程式代碼:

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

您可以將它變更為這個,以修正任何建置錯誤:

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

介面名稱變更

作業群組介面名稱已全部變更為與其對應的屬性名稱一致:

  • ISearchServiceClient.Indexes的類型已從 IIndexOperations 重新命名為 IIndexesOperations。
  • ISearchServiceClient.Indexers的類型已從 IIndexerOperations 重新命名為 IIndexersOperations。
  • ISearchServiceClient.DataSources的類型已從 IDataSourceOperations 重新命名為 IDataSourcesOperations。
  • ISearchIndexClient.Documents的類型已從 IDocumentOperations 重新命名為 IDocumentsOperations。

除非您為了測試目的建立這些介面的模擬,否則這項變更不太可能影響您的程序代碼。

1.1 版的錯誤修正

舊版的 Azure 搜尋服務 .NET SDK 中有與自定義模型類別串行化相關的 Bug。 如果您建立了一個具有不可為 Null 實值型別屬性的自定義模型類別,可能會發生錯誤。

重現的步驟

建立具有不可為 Null 值類型屬性的自定義模型類別。 例如,新增一個UnitCount類型為int的公用屬性,而不是int?。

如果您使用該類型的預設值(例如,int 的預設值為 0)來編製文件索引,則在 Azure 搜尋服務中,該欄位將為空值。 如果您隨後搜尋該檔案, Search 呼叫會擲回 JsonSerializationException 抱怨它無法轉換成 nullint。

此外,篩選可能無法如預期般運作,因為 null 已寫入索引,而不是預期的值。

修正詳細數據

我們已修正 SDK 1.1 版中的此問題。 現在,如果您有如下所示的模型類別:

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

    public int IntValue { get; set; }
}

而且您將 IntValue 設定為 0 時,該值現在會正確地序列化為線路上的 0,並在索引中儲存為 0。 來回行程也會如預期般運作。

此方法有一個可能要注意的問題:如果您使用具有不可為 Null 屬性的模型類型,您必須保證您的索引中沒有任何文件包含對應欄位的 Null 值。 SDK 和 Azure 搜尋服務 REST API 都無法協助您強制執行此作業。

這不僅僅是假設問題:想像一個情境,您在現有索引中加入一個新欄位,而該索引的類型是Edm.Int32。 更新索引定義之後,所有文件都會有該新欄位的 Null 值(因為所有類型在 Azure 搜尋服務中都是可為 Null 的)。 如果您接著使用具有非可為 Null int 屬性的模型類別來處理該欄位,當您嘗試擷取檔時,將會收到類似的 JsonSerializationException:

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

基於這個理由,我們仍然建議您在模型類別中使用可為 Null 的類型作為最佳做法。

如需此 Bug 和修正的詳細資訊,請參閱 GitHub 上的此問題。