Привязки Cosmos DB для F # Azure Функция не связывается - PullRequest
1 голос
/ 19 февраля 2020

Я пытаюсь создать функцию Azure в F #, которая имеет триггер HTTP и которая получает данные из базы данных Cosmos. Документация содержит только примеры в C# для привязки CosmosDB, а перевод кода приводит к ошибке Cannot bind parameter 'toDoItems' to type IEnumerable`1

В этом примере C# можно регистрировать идентификаторы элементов. в космосе:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;

namespace Customer
{
    public class ToDoItem
    {
        public string Id { get; set; }
        public string PartitionKey { get; set; }
        public string Description { get; set; }
    }

    public static class DocByIdFromQueryString
    {
        [FunctionName("Triggered")]
        public static IActionResult Run(
            [HttpTrigger(
                AuthorizationLevel.Anonymous,
                "get",
                Route = null
            )] HttpRequest req,
            [CosmosDB(
                databaseName: "customer-db",
                collectionName: "todo-collection",
                ConnectionStringSetting = "CosmosDBConnection",
                SqlQuery = "select * from c"
            )] IEnumerable<ToDoItem> toDoItems, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            foreach (ToDoItem toDoItem in toDoItems)
            {
                log.LogInformation(toDoItem.Id);
            }
            return new OkResult();
        }
    }
}

Это перевод F # из рабочего C# кода. Оба примера имеют одинаковые версии зависимостей и используют одну и ту же базу данных (и строку подключения).

namespace Customer

open Microsoft.AspNetCore.Http
open Microsoft.AspNetCore.Mvc
open Microsoft.Azure.WebJobs
open Microsoft.Azure.WebJobs.Extensions.Http
open Microsoft.Extensions.Logging


module CosmosBindings =
    type ToDoItem = {
        Id : string
        PartitionKey : string
        Description : string
    }

    [<FunctionName("HttpTrigger")>]
    let Run([<HttpTrigger(
                AuthorizationLevel.Anonymous,
                "get",
                Route = null
            )>] req: HttpRequest,
            [<CosmosDB(
                databaseName = "customer-db",
                collectionName = "todo-collection",
                ConnectionStringSetting = "CosmosDBConnection",
                SqlQuery = "select * from c"
            )>] toDoItems: ToDoItem seq) (log: ILogger) =
                log.LogInformation "F# HTTP trigger function processed a request."

                toDoItems
                |> Seq.iter (fun item -> log.LogInformation item.Id)

                OkObjectResult("Hello")

Я пытался указать привязки в файле функции. json, но независимо от того, что там добавлено, Файл в bin / HttpTrigger / function. json содержит только HttpTrigger (оба C# и F #):

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-3.0.1",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "httpTrigger",
      "methods": [
        "get"
      ],
      "authLevel": "anonymous",
      "name": "req"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/Customer.dll",
  "entryPoint": "Customer.CosmosBindings.Run"
}

Зависимости и версия функции одинаковы для C# и F #:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.3" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.1" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="GetCustomer.fs" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Ошибки при запуске примера F #:

[2/19/2020 4:01:52 PM] Starting JobHost
[2/19/2020 4:01:52 PM] Starting Host (HostId=havardandaestensenvippsnosmacboo, InstanceId=faf11b1c-b81d-49d2-8876-e4ef8785dc9f, Version=3.0.13107, ProcessId=30665, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
[2/19/2020 4:01:52 PM] Loading functions metadata
[2/19/2020 4:01:52 PM] 1 functions loaded
[2/19/2020 4:01:52 PM] Generating 1 job function(s)
[2/19/2020 4:01:52 PM] Microsoft.Azure.WebJobs.Host: Error indexing method 'HttpTrigger'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'toDoItems' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:01:52 PM] Error indexing method 'HttpTrigger'
[2/19/2020 4:01:52 PM] Microsoft.Azure.WebJobs.Host: Error indexing method 'HttpTrigger'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'toDoItems' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:01:52 PM] Function 'HttpTrigger' failed indexing and will be disabled.
[2/19/2020 4:01:52 PM] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:01:52 PM] Initializing function HTTP routes
[2/19/2020 4:01:52 PM] Mapped function route 'api/HttpTrigger' [get] to 'HttpTrigger'
[2/19/2020 4:01:52 PM]
[2/19/2020 4:01:52 PM] Host initialized (199ms)
[2/19/2020 4:01:52 PM] Host started (206ms)
[2/19/2020 4:01:52 PM] Job host started
[2/19/2020 4:01:52 PM] The 'HttpTrigger' function is in error: Microsoft.Azure.WebJobs.Host: Error indexing method 'HttpTrigger'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'toDoItems' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).

Удаление типа из кода F # и просто возврат toDoItems из CosmosDB также приводит к ошибке.

[2/19/2020 4:22:33 PM] Generating 1 job function(s)
[2/19/2020 4:22:33 PM] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
[2/19/2020 4:22:33 PM] Initializing function HTTP routes

Ответы [ 2 ]

0 голосов
/ 03 марта 2020

Оказывается, есть ошибка в шаблоне F #, который используется для генерации функции. Уже почти год существует открытый выпуск , который вы должны использовать Include вместо Update для host.json и local.settings.json. Это правильный .fsproj файл:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.3" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.1" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="GetCustomer.fs" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </Content>
  </ItemGroup>
</Project>

Я озадачен, почему вы должны указать тип возврата выходной переменной. Я считаю, что F # совершенно не подходит для этого. И сообщение об ошибке не помогает при отладке:

[3/3/2020 11:57:09 AM] An unhandled host error has occurred.
[3/3/2020 11:57:09 AM] Microsoft.Azure.WebJobs.Host: 'HttpTrigger' can't be invoked from Azure WebJobs SDK. Is it missing Azure WebJobs SDK attributes?.

Для записи toDoItems: ToDoItem seq и toDoItems: IEnumerable<ToDoItem> оба дают одинаковый результат.

0 голосов
/ 20 февраля 2020

Не так много документации по F # и привязкам, но на основании этого: https://docs.microsoft.com/azure/azure-functions/functions-reference-fsharp#binding -to-arguments , похоже, что выходные переменные используют byref<>, а для входных переменных типы должны быть украшенным [<CLIMutable>].

В этом случае, будучи IEnumerable в C#, я не уверен, нужен ли Seq.cast вместо seq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...