字符串长度超过 32768 个字符时出现 Azure 存储异常
Azure Storage exception when a string length is more than 32768 characters
我的应用程序是 ASP.NET Core 1.0 Web API。如果我的控制器 return 是一个小字符串,则一切正常。但是如果字符串长度超过 32768,我会收到以下错误消息:
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Htpp.Frame`1.<RequestProcessAsync>d__2.MoveNext()
Request Information
RequestID:440ed7db-0002-006f-742e-a28f82000000
RequestDate:Tue, 21 Mar 2017 11:30:40 GMT
StatusMessage:Bad Request
ErrorCode:PropertyValueTooLarge
这是我的控制器:
[HttpGet]
[Produces("plain/text")]
public async Task<IActionResult> GetData()
{
return this.Ok(this.GetResponse());
}
private string GetResponse()
{
string retVal = string.Empty;
for (int i = 0; i < 32769; i++)
{
retVal = retVal + "a";
}
return retVal;
}
完整的错误信息:
Microsoft.WindowsAzure.Storage.StorageException: BadRequest
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.<ExecuteAsyncInternal>d__4`1.MoveNext() in C:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\Windows Runtime\Core\Executor\Executor.cs:line 315
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompillerServices.TaskAwaiter`1.GetResult()
at MyProjectNameLogging.AzureStorageLoggingConnector.<WriteToRequestLogAsync>d__4.MoveNext() in AzureStorageLoggingTable.cs:line 29
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.GetResult()
at MyProjectNameLogging.Repositories.RequestLoggingRepository.<WriteToLogAsync>d__6.MoveNext() in Repositories\RequestLoggingRepository.cs:line 36
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.GetResult()
at MyProjectNameLogging.Middleware.RequestMiddleware.<Invoke>d__2.MoveNext() in Middleware\RequestMiddleware.cs:line 69
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.SwaggerUi.Application.SwaggerUiMiddleware.<Invoke>d__5.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.SwaggerUi.Application.RedirectMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.Swagger.Application.SwaggerMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.<Invoke>d__8.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Hosting.Internal.RequestServiceContainerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Htpp.Frame`1.<RequestProcessAsync>d__2.MoveNext()
Request Information
RequestID:6d8afaf4-0002-00cd-1235-a2421e000000
RequestDate:Tue, 21 Mar 2017 12:24:57 GMT
StatusMessage:Bad Request
ErrorCode:PropertyValueTooLarge
我想要 return 比 32768 更长的字符串。
有什么建议吗?
试试这个:
return new ContentResult { Content = this.GetResponse(), StatusCode = 200 };
您遇到了字符串 属性 类型 (source) 的 Azure 存储限制:
Edm.String (String) - A UTF-16-encoded value. String values may be up to 64 KB in size.
由于 UTF-16 编码的字符串需要 2 个字节来存储一个字符,因此字符串的最大长度为 32768 个字符。
虽然这个问题已经得到解答,但我想为可能遇到此话题的其他人提出解决方案。我需要在 table 实体中的单个 属性 中存储超过 64k 的数据。我在网上找到了一些关于 Lokad Fat Entities 的参考资料,但是,它似乎不再受到积极支持,而且我在 NuGet.org 上可用的版本中遇到了运行时错误。因此,这里是受 Lokad 解决方案启发的 class。我希望其他人觉得它有用。
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;
}
}
}
}
}
示例用法:
public class RawDataBlockEntity : ExtEntity<RawDataBlock>
{
public RawDataBlockEntity(string rawDataId, string blockId, RawDataBlock block)
{
this.PartitionKey = rawDataId;
this.RowKey = blockId;
this.Value = block;
}
public RawDataBlockEntity() { }
}
我的应用程序是 ASP.NET Core 1.0 Web API。如果我的控制器 return 是一个小字符串,则一切正常。但是如果字符串长度超过 32768,我会收到以下错误消息:
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Htpp.Frame`1.<RequestProcessAsync>d__2.MoveNext()
Request Information
RequestID:440ed7db-0002-006f-742e-a28f82000000
RequestDate:Tue, 21 Mar 2017 11:30:40 GMT
StatusMessage:Bad Request
ErrorCode:PropertyValueTooLarge
这是我的控制器:
[HttpGet]
[Produces("plain/text")]
public async Task<IActionResult> GetData()
{
return this.Ok(this.GetResponse());
}
private string GetResponse()
{
string retVal = string.Empty;
for (int i = 0; i < 32769; i++)
{
retVal = retVal + "a";
}
return retVal;
}
完整的错误信息:
Microsoft.WindowsAzure.Storage.StorageException: BadRequest
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.<ExecuteAsyncInternal>d__4`1.MoveNext() in C:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\Windows Runtime\Core\Executor\Executor.cs:line 315
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompillerServices.TaskAwaiter`1.GetResult()
at MyProjectNameLogging.AzureStorageLoggingConnector.<WriteToRequestLogAsync>d__4.MoveNext() in AzureStorageLoggingTable.cs:line 29
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.GetResult()
at MyProjectNameLogging.Repositories.RequestLoggingRepository.<WriteToLogAsync>d__6.MoveNext() in Repositories\RequestLoggingRepository.cs:line 36
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.GetResult()
at MyProjectNameLogging.Middleware.RequestMiddleware.<Invoke>d__2.MoveNext() in Middleware\RequestMiddleware.cs:line 69
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.SwaggerUi.Application.SwaggerUiMiddleware.<Invoke>d__5.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.SwaggerUi.Application.RedirectMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.Swagger.Application.SwaggerMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.<Invoke>d__8.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Hosting.Internal.RequestServiceContainerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace previous location where exception was thrown ---
at System.Runtime.CompillerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompillerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Htpp.Frame`1.<RequestProcessAsync>d__2.MoveNext()
Request Information
RequestID:6d8afaf4-0002-00cd-1235-a2421e000000
RequestDate:Tue, 21 Mar 2017 12:24:57 GMT
StatusMessage:Bad Request
ErrorCode:PropertyValueTooLarge
我想要 return 比 32768 更长的字符串。
有什么建议吗?
试试这个:
return new ContentResult { Content = this.GetResponse(), StatusCode = 200 };
您遇到了字符串 属性 类型 (source) 的 Azure 存储限制:
Edm.String (String) - A UTF-16-encoded value. String values may be up to 64 KB in size.
由于 UTF-16 编码的字符串需要 2 个字节来存储一个字符,因此字符串的最大长度为 32768 个字符。
虽然这个问题已经得到解答,但我想为可能遇到此话题的其他人提出解决方案。我需要在 table 实体中的单个 属性 中存储超过 64k 的数据。我在网上找到了一些关于 Lokad Fat Entities 的参考资料,但是,它似乎不再受到积极支持,而且我在 NuGet.org 上可用的版本中遇到了运行时错误。因此,这里是受 Lokad 解决方案启发的 class。我希望其他人觉得它有用。
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;
}
}
}
}
}
示例用法:
public class RawDataBlockEntity : ExtEntity<RawDataBlock>
{
public RawDataBlockEntity(string rawDataId, string blockId, RawDataBlock block)
{
this.PartitionKey = rawDataId;
this.RowKey = blockId;
this.Value = block;
}
public RawDataBlockEntity() { }
}