Я уверен, что здесь мне не хватает чего-то простого, но я не могу заставить это работать. Я установил симулятор хранилища Azure локально и создал функцию Azure 2.0 с помощью Visual Studio 2019.
Я могу запустить функцию без привязки CosmosDb следующим образом:
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"EndpointUri": "https://localhost:8081",
"PrimaryKey": "<KEY_HERE>"
}
}
Function.cs
public static class Function
{
[FunctionName("func")]
public static async Task Run(
[TimerTrigger("0 * * * * *")] TimerInfo myTimer,
ILogger log
)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
var endpointUri = new Uri(Environment.GetEnvironmentVariable("EndpointUri", EnvironmentVariableTarget.Process));
var primaryKey = Environment.GetEnvironmentVariable("PrimaryKey");
using (var client = new DocumentClient(endpointUri, primaryKey))
{
var queryOptions = new FeedOptions { MaxItemCount = -1 };
var documents = client.CreateDocumentQuery<Doc>(UriFactory.CreateDocumentCollectionUri("db_id", "col_id"), queryOptions);
foreach (var document in documents)
{
...
}
}
}
}
Код работает, как и ожидалось, и получает документы, которые есть у меня в эмуляторе локального хранилища.
Я хотел бы переключить это, чтобы использовать привязку CosmosDb, и, похоже, не могу найти магические заклинания, необходимые для его работы.
Я обновил сигнатуру метода на Function.cs
до:
public static async Task Run(
[TimerTrigger("0 * * * * *")] TimerInfo myTimer,
ILogger log,
[CosmosDB(
databaseName: "db_id",
collectionName: "col_id",
ConnectionStringSetting = "AzureWebJobsStorage",
SqlQuery = "SELECT * FROM col_id")
] IEnumerable<Doc> documents
)
Однако, когда я запускаю его, я получаю следующую ошибку:
[5/17/2019 3:09:29 PM] Executed 'func' (Failed, Id=8326b1c4-3dd5-461d-b8de-d777c5b925d8) [5/17/2019 3:09:29 PM] System.Private.CoreLib: Exception while executing function: func. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'documents'. Microsoft.Azure.DocumentDB.Core: Value cannot be null. [5/17/2019 3:09:29 PM] Parameter name: authKeyOrResourceToken.
Я пробовал ряд других манипуляций, все безуспешно.
Первый заключался в использовании полной явной строки подключения по умолчанию:
"AzureWebJobsStorage": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;",
как в файле Документы Azure.
Любая идея, как я могу изменить приведенное выше, чтобы успешно выполняться локально на моем эмуляторе хранилища Azure?
ConnectionStringSetting
в привязке CosmosDB
— это параметр строки подключения для учетной записи Cosmos DB, а не для хранилища Azure. См. официальные документы для каждого атрибута.
Шаг 1. Добавьте новый параметр в свой local.settings.json
с действительной строкой подключения Cosmos DB (это может быть эмулятор).
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"EndpointUri": "https://localhost:8081",
"PrimaryKey": "<KEY_HERE>",
"CosmosDBConnectionString": "AccountEndpoint=https://localhost:8081;AccountKey=<KEY_HERE>;",
}
}
Шаг 2: Измените свой Function.cs
, чтобы использовать эту новую настройку:
public static async Task Run(
[TimerTrigger("0 * * * * *")] TimerInfo myTimer,
ILogger log,
[CosmosDB(
databaseName: "db_id",
collectionName: "col_id",
ConnectionStringSetting = "CosmosDBConnectionString",
SqlQuery = "SELECT * FROM col_id")
] IEnumerable<Doc> documents
)
При желании вы всегда можете получить экземпляр DocumentClient
из привязки, если хотите вручную запустить запрос или выполнить другие операции:
public static async Task Run(
[TimerTrigger("0 * * * * *")] TimerInfo myTimer,
ILogger log,
[CosmosDB(
databaseName: "db_id",
collectionName: "col_id",
ConnectionStringSetting = "CosmosDBConnectionString")
] DocumentClient documentClient
)
As a side note, whenever you are creating a
DocumentClient
manually, please follow these guidelines, never create aDocumentClient
instance within ausing
statement in each execution.
В документе есть специальный раздел для DocumentClient
, потому что рекомендации по производительности Cosmos DB говорит об использовании шаблона Singleton. Частично это связано с тем, что клиент использует HttpClient
внутри. Все сводится к aspnetmonsters.com/2016/08/2016-08-27-httpclientнеправильно
Спасибо за очень полезный ответ. re:
using
, документы говорят вам не помещатьHttpClient
в использование. Является лиDocumentClient
просто оберткой вокруг этого, поэтому вы не должны использовать для него операторusing
?