0

I have the following class:

public class MyData
{
  public string PartitionKey { get; set; }
  public string RowKey { get; set; }
  public int NumOranges { get; set; }
  public int NumApples { get; set; }
  public int NumBananas { get; set; }
}

I am writing instances to Azure Table Storage using the .NET 8 Isolated Azure Functions TableOutput binding.

When I attempt to read the data using Azure.Data.Table.TableClient (v12.10.0) like this:

  var result = tableClient.Query<MyData>(filter: d => d.PartitionKey = 'val');

I get Unable to cast object of type 'System.String' to type 'System.Int32' errors.

I though table storage was schema-less.

If I change the type of all my int properties to long then it works. I can use that as a workaround but I would love to know the cause and if I can do something more preventative or logical about it.

The issue is not to do with the actual values. All values are well within the Int32.MaxValue. I have double-checked by getting the data as TableEntity and checked the Max() of each property.

0

1 Answer 1

0

Azure Table Storage stores numbers as long (Edm.Int64), so I have used Convert.ToInt32(entity["PropertyName"]) to read them as int and avoid type mismatches.

ReadFromTableStorage.cs :

using System.Net;
using Azure.Data.Tables;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using Azure;
using FunctionApp28.Models;

namespace FunctionApp28.Functions
{
    public static class ReadFromTableStorage
    {
        [Function("ReadFromTableStorage")]
        public static async Task<HttpResponseData> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req,
            FunctionContext executionContext)
        {
            var logger = executionContext.GetLogger("ReadFromTableStorage");
            logger.LogInformation("Reading from Azure Table Storage...");

            string connectionString = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
            string tableName = "kamtable";

            if (string.IsNullOrEmpty(connectionString))
            {
                logger.LogError("AzureWebJobsStorage connection string is missing.");
                var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError);
                await errorResponse.WriteStringAsync("Storage connection string not found.");
                return errorResponse;
            }

            try
            {
                var tableClient = new TableClient(connectionString, tableName);
                Pageable<TableEntity> entities = tableClient.Query<TableEntity>();
                var resultList = new List<MyData>();
                foreach (var entity in entities)
                {
                    resultList.Add(new MyData
                    {
                        PartitionKey = entity.PartitionKey,
                        RowKey = entity.RowKey,
                        NumOranges = entity.ContainsKey("NumOranges") ? Convert.ToInt32(entity["NumOranges"]) : 0,
                        NumApples = entity.ContainsKey("NumApples") ? Convert.ToInt32(entity["NumApples"]) : 0,
                        NumBananas = entity.ContainsKey("NumBananas") ? Convert.ToInt32(entity["NumBananas"]) : 0
                    });
                }

                var response = req.CreateResponse(HttpStatusCode.OK);
                await response.WriteStringAsync(JsonSerializer.Serialize(resultList));
                return response;
            }
            catch (Exception ex)
            {
                logger.LogError($"Error reading from Table Storage: {ex.Message}");
                var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError);
                await errorResponse.WriteStringAsync($"Error retrieving data: {ex.Message}");
                return errorResponse;
            }
        }
    }
}

WriteToTableStorage.cs :

using System.Net;
using Azure.Data.Tables;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using FunctionApp28.Models;

namespace FunctionApp28.Functions
{
    public static class WriteToTableStorage
    {
        private const string TableName = "kamtable";
        [Function("WriteToTableStorage")]
        public static async Task<HttpResponseData> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req,
            FunctionContext context)
        {
            var logger = context.GetLogger("WriteToTableStorage");
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var data = JsonConvert.DeserializeObject<MyData>(requestBody);

            if (data == null)
            {
                var badResponse = req.CreateResponse(HttpStatusCode.BadRequest);
                await badResponse.WriteStringAsync("Invalid request payload.");
                return badResponse;
            }

            string connectionString = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
            var tableClient = new TableClient(connectionString, TableName);
            await tableClient.CreateIfNotExistsAsync();

            var entity = new TableEntity(data.PartitionKey, data.RowKey)
            {
                { "NumOranges", data.NumOranges },
                { "NumApples", data.NumApples },
                { "NumBananas", data.NumBananas }
            };

            await tableClient.AddEntityAsync(entity);
            logger.LogInformation("Data written to table storage successfully.");
            var response = req.CreateResponse(HttpStatusCode.OK);
            await response.WriteStringAsync("Entity written to Table Storage.");
            return response;
        }
    }
}

MyData.cs :

namespace FunctionApp28.Models
{
    public class MyData
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }
        public int NumOranges { get; set; }
        public int NumApples { get; set; }
        public int NumBananas { get; set; }
    }
}

Output :

I have sent the below POST request.

{
    "PartitionKey": "Fruit",
    "RowKey": "123",
    "NumOranges": 5,
    "NumApples": 10,
    "NumBananas": 3
}

enter image description here

enter image description here

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.