Tingkatkan ke Azure Search .NET SDK versi 1.1

Jika Anda menggunakan pratinjau versi 1.0.2 atau yang lebih lama dari Azure Search .NET SDK, artikel ini akan membantu Anda meningkatkan aplikasi Anda untuk menggunakan versi 1.1.

Untuk panduan SDK yang lebih umum termasuk contoh, lihat Cara menggunakan Azure Search dari Aplikasi .NET.

Nota

Setelah Anda meningkatkan ke versi 1.1, atau jika Anda sudah menggunakan versi antara 1.1 dan 2.0-preview inklusif, Anda harus meningkatkan ke versi 3. Lihat Pemutakhiran ke Azure Search .NET SDK versi 3 untuk instruksi.

Pertama, perbarui referensi NuGet Anda untuk Microsoft.Azure.Search menggunakan Konsol Manajer Paket NuGet atau dengan mengklik kanan referensi proyek Anda dan memilih "Kelola Paket NuGet..." di Visual Studio.

Setelah NuGet mengunduh paket baru dan dependensinya, bangun kembali proyek Anda.

Jika sebelumnya Anda menggunakan pratinjau versi 1.0.0, pratinjau 1.0.1, atau pratinjau 1.0.2, build akan berhasil dan Anda siap untuk memulai!

Jika sebelumnya Anda menggunakan pratinjau versi 0.13.0 atau yang lebih lama, Anda akan melihat kesalahan build seperti berikut ini:

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

Langkah selanjutnya adalah memperbaiki kesalahan build satu per satu. Sebagian besar akan memerlukan perubahan beberapa nama kelas dan metode yang telah diganti namanya di SDK. Daftar perubahan signifikan di versi 1.1 berisi perubahan penting ini.

Jika Anda menggunakan kelas kustom untuk memodelkan dokumen Anda, dan kelas tersebut memiliki properti jenis primitif yang tidak dapat diubah ke null (misalnya, int atau bool di C#), ada perbaikan bug dalam versi 1.1 dari SDK yang harus Anda ketahui. Lihat perbaikan bug di versi 1.1 untuk detail selengkapnya.

Terakhir, setelah memperbaiki kesalahan build, Anda dapat membuat perubahan pada aplikasi untuk memanfaatkan fungsionalitas baru jika mau.

Daftar perubahan mencolok dalam versi 1.1

Daftar berikut diurutkan berdasarkan kemungkinan perubahan akan memengaruhi kode aplikasi Anda.

Perubahan IndexBatch dan IndexAction

IndexBatch.Create telah diganti namanya menjadi IndexBatch.New dan tidak lagi memiliki argumen params. Anda dapat menggunakan IndexBatch.New untuk batch yang mencampur berbagai jenis tindakan (menggabungkan, menghapus, dll.). Selain itu, ada metode statis baru untuk membuat batch di mana semua tindakan sama: Delete, Merge, MergeOrUpload, dan Upload.

IndexAction tidak lagi memiliki konstruktor publik dan propertinya sekarang tidak dapat diubah. Anda harus menggunakan metode statis baru untuk membuat tindakan untuk tujuan yang berbeda: Delete, Merge, MergeOrUpload, dan Upload. IndexAction.Create telah dihapus. Jika Anda menggunakan fungsi overload yang hanya memproses dokumen, pastikan untuk menggunakan Upload sebagai gantinya.

Contoh

Jika kode Anda terlihat seperti ini:

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

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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

Jika mau, Anda dapat lebih menyederhanakannya dengan ini:

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

Perubahan pada IndexBatchException

Properti IndexBatchException.IndexResponse telah diganti namanya menjadi IndexingResults, dan jenisnya sekarang IList<IndexingResult>.

Contoh

Jika kode Anda terlihat seperti ini:

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

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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

Perubahan metode operasi

Setiap operasi di Azure Search .NET SDK diekspos sebagai sekumpulan metode kelebihan beban untuk penelepon sinkron dan asinkron. Tanda tangan dan faktor kelebihan beban metode ini telah berubah dalam versi 1.1.

Misalnya, operasi "Dapatkan Statistik Indeks" dalam versi SDK yang lebih lama mengekspos tanda tangan ini:

Dalam IIndexOperations:

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

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

Tanda tangan metode untuk operasi yang sama di versi 1.1 terlihat seperti ini:

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

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

Dimulai dengan versi 1.1, Azure Search .NET SDK mengatur metode operasi secara berbeda:

  • Parameter opsional sekarang dimodelkan sebagai parameter default daripada kelebihan beban metode tambahan. Ini mengurangi jumlah kelebihan metode, kadang-kadang secara dramatis.
  • Metode ekstensi sekarang menyembunyikan banyak detail HTTP yang asing dari pemanggil. Misalnya, versi SDK yang lebih lama mengembalikan objek respons dengan kode status HTTP, yang sering tidak perlu Anda periksa karena metode operasi melemparkan CloudException untuk kode status apa pun yang menunjukkan kesalahan. Metode ekstensi baru hanya mengembalikan objek model, sehingga Anda tidak perlu membongkarnya dalam kode Anda.
  • Sebaliknya, antarmuka inti sekarang mengekspos metode yang memberi Anda lebih banyak kontrol di tingkat HTTP jika Anda membutuhkannya. Anda sekarang dapat memasukkan header HTTP kustom dalam permintaan, dan jenis pengembalian AzureOperationResponse<T> baru memberikan Anda akses langsung ke HttpRequestMessage dan HttpResponseMessage untuk operasi. AzureOperationResponse didefinisikan dalam namespace Microsoft.Rest.Azure dan menggantikan Hyak.Common.OperationResponse.

Perubahan Parameter Penilaian

Kelas baru bernama ScoringParameter telah ditambahkan di SDK terbaru untuk mempermudah penyediaan parameter ke profil penilaian dalam kueri pencarian. Sebelumnya properti ScoringProfiles dari kelas SearchParameters ditik sebagai IList<string>; Sekarang diketik sebagai IList<ScoringParameter>.

Contoh

Jika kode Anda terlihat seperti ini:

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

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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

Perubahan pada kelas model

Karena perubahan tanda tangan yang dijelaskan dalam Perubahan metode Operasi, banyak kelas di namespace Microsoft.Azure.Search.Models telah diganti namanya atau dihapus. Contohnya:

  • IndexDefinitionResponse digantikan oleh AzureOperationResponse<Index>
  • DocumentSearchResponse telah diubah namanya menjadi DocumentSearchResult
  • IndexResult telah diubah namanya menjadi IndexingResult
  • Documents.Count() sekarang mengembalikan long yang berisi jumlah dokumen alih-alih DocumentCountResponse
  • IndexGetStatisticsResponse telah diubah namanya menjadi IndexGetStatisticsResult
  • IndexListResponse telah diubah namanya menjadi IndexListResult

Untuk meringkas, OperationResponsekelas turunan yang hanya ada untuk membungkus objek model telah dihapus. Kelas yang tersisa telah diubah akhiran mereka dari Response menjadi Result.

Contoh

Jika kode Anda terlihat seperti ini:

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;

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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;

Kelas respons dan *IEnumerable*

Perubahan tambahan yang dapat memengaruhi kode Anda adalah bahwa kelas respons yang menyimpan koleksi tidak lagi menerapkan IEnumerable<T>. Sebagai gantinya, Anda dapat mengakses properti koleksi secara langsung. Misalnya, jika kode Anda terlihat seperti ini:

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

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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

Kasus khusus untuk aplikasi web

Jika Anda memiliki aplikasi web yang menserialisasikan DocumentSearchResponse secara langsung untuk mengirim hasil pencarian ke browser, Anda harus mengubah kode Anda atau hasilnya tidak akan diserialisasikan dengan benar. Misalnya, jika kode Anda terlihat seperti ini:

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

Anda dapat mengubahnya dengan mendapatkan properti .Results respons pencarian untuk memperbaiki penyajian hasil pencarian:

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

Anda harus mencari kasus seperti itu dalam kode Anda sendiri; Pengkompilasi tidak akan memperingatkan Anda karena JsonResult.Data berjenis object.

Perubahan pada CloudException

Kelas CloudException telah berpindah dari namespace Hyak.Common ke namespace Microsoft.Rest.Azure. Selain itu, properti Error telah diganti namanya menjadi Body.

Perubahan SearchServiceClient dan SearchIndexClient

Jenis properti Credentials telah berubah dari SearchCredentials ke kelas dasarnya, ServiceClientCredentials. Jika Anda perlu mengakses SearchCredentials dari SearchIndexClient atau SearchServiceClient, silakan gunakan properti SearchCredentials yang baru.

Dalam versi SDK yang lebih lama, SearchServiceClient dan SearchIndexClient memiliki konstruktor yang mengambil parameter HttpClient. Ini telah diganti dengan konstruktor yang menerima HttpClientHandler dan array objek DelegatingHandler. Ini membuatnya lebih mudah untuk menginstal handler kustom untuk memproses permintaan HTTP sebelum diproses jika perlu.

Akhirnya, konstruktor yang mengambil Uri dan SearchCredentials telah berubah. Misalnya, jika Anda memiliki kode yang terlihat seperti ini:

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

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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

Harap dicatat juga bahwa jenis parameter kredensial telah berubah menjadi ServiceClientCredentials. Ini tidak mungkin memengaruhi kode Anda karena SearchCredentials berasal dari ServiceClientCredentials.

Meneruskan ID permintaan

Dalam versi SDK yang lebih lama, Anda dapat mengatur ID permintaan pada SearchServiceClient atau SearchIndexClient dan itu akan disertakan dalam setiap permintaan ke REST API. Ini berguna untuk memecahkan masalah dengan layanan pencarian Anda jika Anda perlu menghubungi dukungan. Namun, lebih berguna untuk mengatur ID permintaan unik untuk setiap operasi daripada menggunakan ID yang sama untuk semua operasi. Untuk alasan ini, metode SetClientRequestId, SearchServiceClient, dan SearchIndexClient telah dihapus. Sebagai gantinya, Anda dapat meneruskan ID permintaan ke setiap metode operasi melalui parameter SearchRequestOptions opsional.

Nota

Dalam rilis SDK di masa mendatang, kami akan menambahkan mekanisme baru untuk mengatur ID permintaan secara global pada objek klien yang konsisten dengan pendekatan yang digunakan oleh Azure SDK lainnya.

Contoh

Jika Anda memiliki kode yang terlihat seperti ini:

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

Anda dapat mengubahnya menjadi ini untuk memperbaiki kesalahan build apa pun:

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

Perubahan nama antarmuka

Nama antarmuka grup operasi semuanya telah berubah agar konsisten dengan nama properti yang sesuai:

  • Jenis ISearchServiceClient.Indexes telah diganti namanya dari IIndexOperations menjadi IIndexesOperations.
  • Jenis ISearchServiceClient.Indexers telah diganti namanya dari IIndexerOperations menjadi IIndexersOperations.
  • Jenis ISearchServiceClient.DataSources telah diganti namanya dari IDataSourceOperations menjadi IDataSourcesOperations.
  • Jenis ISearchIndexClient.Documents telah diganti namanya dari IDocumentOperations menjadi IDocumentsOperations.

Perubahan ini tidak mungkin memengaruhi kode Anda kecuali Anda membuat tiruan antarmuka ini untuk tujuan pengujian.

Perbaikan bug di versi 1.1

Ada bug di versi lama Azure Search .NET SDK yang berkaitan dengan serialisasi kelas model kustom. Bug ini bisa terjadi jika Anda membuat kelas model kustom dengan properti dari jenis nilai yang tidak bisa bernilai null.

Langkah-langkah untuk mereprodusi

Buat kelas model kustom dengan properti jenis nilai yang tidak dapat diubah ke null. Misalnya, tambahkan properti UnitCount publik jenis int alih-alih int?.

Jika Anda mengindeks dokumen dengan nilai default jenis tersebut (misalnya, 0 untuk int), bidang akan null di Azure Search. Jika Anda kemudian mencari dokumen tersebut, panggilan Search akan memberikan pesan JsonSerializationException yang mengeluh bahwa tidak dapat mengonversi null ke int.

Selain itu, filter mungkin tidak berfungsi seperti yang diharapkan karena null ditulis ke indeks alih-alih nilai yang dimaksudkan.

Perbaiki detail

Kami telah memperbaiki masalah ini di SDK versi 1.1. Sekarang, jika Anda memiliki kelas model seperti ini:

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

    public int IntValue { get; set; }
}

dan Anda mengatur IntValue ke 0, nilai tersebut sekarang diserialisasikan dengan benar sebagai 0 pada kawat dan disimpan sebagai 0 dalam indeks. Round tripping juga berfungsi seperti yang diharapkan.

Ada satu masalah potensial yang perlu diperhatikan dengan pendekatan ini: Jika Anda menggunakan jenis model dengan properti yang tidak dapat diubah ke null, Anda harus menjamin bahwa tidak ada dokumen dalam indeks Anda yang berisi nilai null untuk bidang yang sesuai. Baik SDK maupun Azure Search REST API tidak akan membantu Anda menerapkannya.

Ini bukan hanya masalah hipotetis: Bayangkan skenario di mana Anda menambahkan bidang baru ke indeks yang ada yang berjenis Edm.Int32. Setelah memperbarui definisi indeks, semua dokumen akan memiliki nilai null untuk bidang baru tersebut (karena semua jenis dapat diubah ke null di Azure Search). Jika Anda kemudian menggunakan kelas model dengan properti int yang tidak dapat diubah ke null untuk bidang tersebut, Anda akan mendapatkan JsonSerializationException seperti ini saat mencoba mengambil dokumen:

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

Untuk alasan ini, kami masih menyarankan agar Anda menggunakan tipe data nullable di kelas model Anda sebagai praktik terbaik.

Untuk detail selengkapnya tentang bug ini dan perbaikannya, silakan lihat masalah ini di GitHub.