Azure Storage exception when a string length is more than 32768 characters

前端 未结 3 1125
悲&欢浪女
悲&欢浪女 2021-01-14 06:40

My application is an ASP.NET Core 1.0 Web API. If my controller returns a small string, everything works fine. But if the string length gets longer than 32768, i\'m getting

相关标签:
3条回答
  • 2021-01-14 07:16

    Though this has already been answered, I'd like to propose solution for anyone else who might come across this thread. I needed to store significantly more than 64k in a single property in my table entity. I found several references online to Lokad Fat Entities, however, it seems it is no longer actively supported and I had runtime errors with the version available on NuGet.org. So, here is a class that is inspired by Lokad's solution. I hope others find it useful.

        public class ExtEntity<T> : TableEntity where T : new()
    {
        private const int MAX_BYTES_PER_ARR = 65500; // don't use full 64k to avoid any weird edge case
    
        // Serialized in DB and deserialized for callers
        public Byte[] A0 { get; set; }
        public Byte[] A1 { get; set; }
        public Byte[] A2 { get; set; }
        public Byte[] A3 { get; set; }
        public Byte[] A4 { get; set; }
        public Byte[] A5 { get; set; }
        public Byte[] A6 { get; set; }
        public Byte[] A7 { get; set; }
        public Byte[] A8 { get; set; }
        public Byte[] A9 { get; set; }
        public Byte[] A10 { get; set; }
        public Byte[] A11 { get; set; }
        public Byte[] A12 { get; set; }
        public Byte[] A13 { get; set; }
        public Byte[] A14 { get; set; }
        public Byte[] A15 { get; set; }
        private T value;
    
        public T Value
        {
            // Accessors automatically serialize and deserialize T value
            get
            {
                // ASSUMES that value will never change after first time deserialized!
                if (this.value == null)
                {
                    int n = 0;
                    using (var memStream = new MemoryStream())
                    {
                        while (true)
                        {
                            string propName = "A" + n++;
                            PropertyInfo prop = this.GetType().GetProperty(propName);
                            byte[] arr = (byte[])prop.GetValue(this);
                            if (arr == null || arr.Length == 0)
                            {
                                break;
                            }
                            memStream.Write(arr, 0, arr.Length);
                        }
                        memStream.Seek(0, SeekOrigin.Begin);
                        var binForm = new BinaryFormatter();
                        this.value = (T)binForm.Deserialize(memStream);
                    }
                }
                return this.value;
            }
            set
            {
                // First, ensure the type is serializable.
                if (!typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T))))
                    throw new InvalidOperationException("ExtEntity<T>.get_Value Exception: A serializable Type is required.");
    
                // Assign the value
                this.value = value;
    
                // Then searialize it for Table Storage use
                BinaryFormatter bf = new BinaryFormatter();
                using (var memStream = new MemoryStream())
                {
                    // Serialize into memory stream, then seek back to origin
                    bf.Serialize(memStream, this.value);
                    memStream.Seek(0, SeekOrigin.Begin);
    
                    // Chunk data from memory stream into stored properties
                    int bytesRemaining = (int)memStream.Length;
                    int n = 0;
                    while (bytesRemaining > 0)
                    {
                        if (n > 15)
                        {
                            throw new ApplicationException("ExtEntity<T>.set_Value Exception: Data is too large.");
                        }
                        int numToRead = Math.Min(bytesRemaining, ExtEntity<T>.MAX_BYTES_PER_ARR);
                        byte[] arr = new byte[numToRead];
                        int numRead = memStream.Read(arr, 0, numToRead);
                        if (numRead != numToRead)
                        {
                            throw new ApplicationException("ExtEntity<T>.set_Value Exception: Unexpected number of bytes returned.");
                        }
    
                        string propName = "A" + n++;
                        PropertyInfo prop = this.GetType().GetProperty(propName);
                        prop.SetValue(this, arr);
                        bytesRemaining -= numRead;
                    }
                }
            }
        }
    }
    

    Sample usage:

    public class RawDataBlockEntity : ExtEntity<RawDataBlock>
    {
        public RawDataBlockEntity(string rawDataId, string blockId, RawDataBlock block)
        {
            this.PartitionKey = rawDataId;
            this.RowKey = blockId;
    
            this.Value = block;
        }
    
        public RawDataBlockEntity() { }
    }
    
    0 讨论(0)
  • 2021-01-14 07:22

    You are encountered the Azure Storage limit for the string property type (source):

    Edm.String (String) - A UTF-16-encoded value. String values may be up to 64 KB in size.

    Because UTF-16 encoded strings require 2 bytes to store an character the maximum string length is 32768 characters.

    0 讨论(0)
  • Try this:

    return new ContentResult { Content = this.GetResponse(), StatusCode = 200 };
    
    0 讨论(0)
提交回复
热议问题