Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Если вы используете версию 1.0.2 или более раннюю версию пакета SDK для поиска Azure .NET, эта статья поможет обновить приложение до версии 1.1.
Более общее пошаговое руководство по пакету SDK с примерами, см. статью Использование службы "Поиск Azure" в приложении .NET.
Примечание.
После обновления до версии 1.1 или если вы уже используете версию от 1.1 до 2.0 включительно, необходимо обновить до версии 3. Инструкции см. в разделе , посвященном обновлению до версии 3 SDK для .NET для Поиска Azure.
Сначала обновите ссылку NuGet для Microsoft.Azure.Search с помощью консоли диспетчера пакетов NuGet или щелкните правой кнопкой мыши ссылки на проекты и выберите пункт "Управление пакетами NuGet..." в Visual Studio.
После того как 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 содержит список этих изменений имен.
Если вы используете пользовательские классы для моделирования документов, и эти классы имеют свойства ненулевых примитивных типов (например, int или bool в C#), в версии 1.1 SDK исправлена ошибка, с которой вам следует ознакомиться. См. исправления ошибок в версии 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 Search .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 пакет SDK для поиска Azure для .NET упорядочивает методы операций по-разному:
- Необязательные параметры теперь моделируются как параметры по умолчанию, а не дополнительные перегрузки методов. Это уменьшает количество перегрузок методов, иногда резко.
- Методы расширения теперь скрывают много избыточных сведений HTTP от вызывающего. Например, старые версии пакета SDK вернули объект ответа с кодом состояния HTTP, который часто не нужно проверять, так как методы операций вызывают
CloudExceptionдля любого кода состояния, указывающего на ошибку. Новые методы расширения просто возвращают объекты модели, избавляя вас от необходимости распаковывать их в вашем коде. - И наоборот, основные интерфейсы теперь предоставляют методы, которые дают вам больше управления на уровне HTTP, если это необходимо. Теперь вы можете передать пользовательские заголовки HTTP для включения в запросы, а новый тип возврата
AzureOperationResponse<T>предоставляет прямой доступ кHttpRequestMessageиHttpResponseMessageдля операции.AzureOperationResponseопределен в пространстве именMicrosoft.Rest.Azureи заменяетHyak.Common.OperationResponse.
Изменения параметров оценки
Новый класс с именем ScoringParameter добавлен в последний пакет SDK, чтобы упростить предоставление параметров профилям оценки в поисковом запросе. Ранее свойство 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))
};
Изменения класса модели
Вследствие изменений в сигнатурах, описанных в разделе 'Изменения метода операции', многие классы в пространстве имен 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);
}
Особый случай для веб-приложений
Если у вас есть веб-приложение, которое сериализует DocumentSearchResponse непосредственно для отправки результатов поиска в браузер, вам потребуется изменить код или результаты не будут сериализоваться правильно. Например, если код выглядит следующим образом:
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. Если вам нужно получить доступ к SearchCredentials, SearchIndexClient или 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.
Передача идентификатора запроса
В более ранних версиях пакета SDK можно задать идентификатор запроса на SearchServiceClient или SearchIndexClient, и он будет включен в каждый запрос к REST API. Это полезно для устранения неполадок со службой поиска, если вам нужно обратиться в службу поддержки. Однако более полезно задать уникальный идентификатор запроса для каждой операции, а не использовать один и тот же идентификатор для всех операций. Методы SetClientRequestId, SearchServiceClient и SearchIndexClient были удалены по этой причине. Вместо этого можно передать идентификатор запроса каждому методу операции с помощью необязательного параметра SearchRequestOptions.
Примечание.
В будущем выпуске пакета SDK мы добавим новый механизм настройки идентификатора запроса глобально для клиентских объектов, которые соответствуют подходу, используемому другими пакетами SDK Azure.
Пример
Если у вас есть код, который выглядит следующим образом:
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
В более ранних версиях пакета SDK для поиска Azure .NET произошла ошибка, связанная с сериализацией пользовательских классов моделей. Ошибка может возникнуть, если вы создали пользовательский класс модели со свойством типа значения, не допускающего значения NULL.
Шаги для воспроизведения
Создайте пользовательский класс модели со свойством ненулевого типа значения. Например, добавьте общедоступное свойство UnitCount типа int вместо int?.
Если индексировать документ со значением по умолчанию этого типа (например, 0 для int), поле будет иметь значение NULL в службе "Поиск Azure". При последующем поиске этого документа вызов Search приведёт к ошибке JsonSerializationException, сообщающей, что не удаётся преобразовать null в int.
Кроме того, фильтры могут не работать должным образом, так как значение NULL было записано в индекс вместо предполагаемого значения.
Исправление сведений
Исправлена эта проблема в версии 1.1 пакета SDK. Теперь, если у вас есть класс модели, как показано ниже:
public class Model
{
public string Key { get; set; }
public int IntValue { get; set; }
}
и вы устанавливаете IntValue на 0, это значение теперь правильно сериализуется как 0 при передаче и сохраняется как 0 в индексе. Циклический обход также работает должным образом.
Существует одна из потенциальных проблем с этим подходом. Если вы используете тип модели с свойством, не допускающим значение NULL, необходимо гарантировать,, что документы в индексе не содержат значение NULL для соответствующего поля. Ни пакет SDK, ни REST API службы поиска Azure не помогут применить это.
Это не просто гипотетическая проблема: представьте сценарий, в котором вы добавляете новое поле в существующий индекс, имеющий тип Edm.Int32. После обновления определения индекса все документы будут иметь значение NULL для этого нового поля (так как все типы имеют значение NULL в службе поиска Azure). Если вы используете класс модели с свойством, не допускающим значение NULL, int для этого поля, вы получите JsonSerializationException, как при попытке получить документы:
Error converting value {null} to type 'System.Int32'. Path 'IntValue'.
По этой причине мы по-прежнему рекомендуем использовать типы, допускающие значение NULL, в классах моделей как наилучшую практику.
Дополнительные сведения об этой ошибке и исправлении см. в этой проблемы наGitHub.