Azure Function Table Binding: Как обновить строку?

Я пытаюсь обновить строку в таблице Azure на основе Azure Function. Я вижу, что привязки таблиц могут обрабатывать ICollector, который имеет метод Add, который добавит строку. Я также вижу, что вы используете IQueryable для чтения данных.

Как вы собираетесь обновлять определенную строку в данных?

Я видел в WebJobs что-то, что связано с InsertOrReplace, которое является методом TableOperations, но я не знаю, что или как это входит в игру и как использовать его с функциями Azure.

Ответ 1

Ниже вы можете сделать это. Эти шаги облегчатся с нашей следующей версией, но теперь вам нужно вручную добавить в Azure Storage SDK.

Сначала выполните шаги в разделе "Управление пакетами" эту страницу справки, чтобы вставить Azure Storage SDK. Вы загрузите project.json, который будет выглядеть в вашей папке:

{
  "frameworks": {
    "net46":{
      "dependencies": {
        "WindowsAzure.Storage": "7.0.0"
      }
    }
   }
}

Примечание. В следующем выпуске мы автоматически включим Azure Storage SDK, чтобы вы могли просто использовать его непосредственно в своем коде. После того, как вы втянули пакет, вы можете ввести метаданные функции, как показано на вкладке Интеграция вкладки. Расширенный редактор:

{
  "bindings": [
    {
      "name": "input",
      "type": "manualTrigger",
      "direction": "in"
    },
    {
      "name": "table",
      "type": "table",
      "tableName": "test",
      "connection": "<your connection>",
      "direction": "in"
    }
  ]
}

И ниже приведен соответствующий код. Мы привязываемся к CloudTable здесь, что позволяет нам читать/записывать объекты:

#r "Microsoft.WindowsAzure.Storage"

using System;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;

public static void Run(string input, CloudTable table, TraceWriter log)
{
    TableOperation operation = TableOperation.Retrieve<Person>("AAA", "001");
    TableResult result = table.Execute(operation);
    Person person = (Person)result.Result;

    log.Verbose($"{person.Name} is {person.Status}");

    person.Status = input;
    operation = TableOperation.Replace(person);
    table.Execute(operation);
}

public class Person : TableEntity
{
    public string Name   { get;set; }
    public string Status { get;set; }
}

В этом примере я использовал ManualTrigger, но привязка таблицы будет работать с любым триггером, который у вас есть. С помощью приведенной выше настройки я могу ввести значение в поле "Запуск ввода" портала и нажать "Бег". Функция будет запрашивать сущность, выводить ее текущие значения, а затем обновлять с использованием моего ввода.

Возможны и другие перестановки. Например, если у вас есть экземпляр объекта из другого параметра привязки, вы можете использовать CloudTable аналогичным образом, чтобы его обновить.

Ответ 2

С текущей версией функций я смог сделать обновления строк работающими с декларативными привязками. Вот пример с триггером HTTP, который увеличивает число в строке Azure Table.

function.json:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "route": "HttpTriggerTableUpdate/{partition}/{rowkey}"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "table",
      "name": "inputEntity",
      "tableName": "SOTrial",
      "partitionKey": "{partition}",
      "rowKey": "{rowkey}",
      "connection": "my_STORAGE",
      "direction": "in"
    },
    {
      "type": "table",
      "name": "outputEntity",
      "tableName": "SOTrial",
      "partitionKey": "{partition}",
      "rowKey": "{rowkey}",
      "connection": "my_STORAGE",
      "direction": "out"
    }
  ],
  "disabled": false
}

Функция С#:

#r "Microsoft.WindowsAzure.Storage"

using System;
using System.Net;
using Microsoft.WindowsAzure.Storage.Table;

public class Entity : TableEntity
{
    public int Number {get; set;}
}

public static HttpResponseMessage Run(HttpRequestMessage req, string partition, 
    string rowkey, Entity inputEntity, out Entity outputEntity)
{
    if (inputEntity == null)
        outputEntity = new Entity { PartitionKey = partition, RowKey = rowkey, Number = 1};
    else
    {
        outputEntity = inputEntity;
        outputEntity.Number += 1;
    }

    return req.CreateResponse(HttpStatusCode.OK, $"Done, Number = {outputEntity.Number}");
}

Ответ 3

С сегодняшними привязками вы можете установить для свойства ETag значение * чтобы выполнить upsert:

[FunctionName("Function1")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log,
    [Table("test")] IAsyncCollector<PocoClass> table)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];
    if (name == null)
        return new BadRequestResult();

    await table.AddAsync(new PocoClass { Name = name });
    return new OkObjectResult($"Hello, {name}");
}

public sealed class PocoClass
{
    public string PartitionKey { get; } = "partition";
    public string RowKey { get; } = "row";
    public string ETag { get; } = "*";
    public string Name { get; set; }
}