C# &引用;操作的意外响应代码:0“;执行Azure表存储批删除时
我正在使用适用于.NET的Windows Azure存储库的4.3.0版。在我的ATS repository类中,我有两个批量删除方法,如下所示:C# &引用;操作的意外响应代码:0“;执行Azure表存储批删除时,c#,azure-storage,C#,Azure Storage,我正在使用适用于.NET的Windows Azure存储库的4.3.0版。在我的ATS repository类中,我有两个批量删除方法,如下所示: public async Task DeleteAsync(IEnumerable<T> entities) { await ExecuteAsBatch(entities, (batch, entity) => batch.Delete(entity)); } private async Task ExecuteAsBa
public async Task DeleteAsync(IEnumerable<T> entities)
{
await ExecuteAsBatch(entities, (batch, entity) => batch.Delete(entity));
}
private async Task ExecuteAsBatch(IEnumerable<T> entities, Action<TableBatchOperation, T> batchAction)
{
var byPartition = entities.GroupBy(x => x.PartitionKey).ToList();
await byPartition.ForEachParallel(async group =>
{
// A maximum of 100 actions are allowed per batch job
var segments = group.ToList().ToSegmentedList(100);
await segments.ForEachParallel(async segment =>
{
var batch = new TableBatchOperation();
foreach (var entity in segment)
{
batchAction(batch, entity);
}
await Table.ExecuteBatchAsync(batch);
}, 10);
}, 10);
}
以下是呼叫站点:
private async Task MergeAtsOrganizationUserEvents(int organizationId, IEnumerable<CustomerUserEvent> fromEvents, CustomerUser to)
{
var toDelete = (await fromEvents.SelectParallel(async fromEvent =>
{
var pkey = AtsOrganizationUserEventByMinute.GetPartitionKey(organizationId, fromEvent.OccurredOn);
var rkey = AtsOrganizationUserEventByMinute.GetRowKey(fromEvent.OccurredOn, fromEvent.CustomerUserEventId);
return await Ats.OrganizationUserEventByMinute.FindByPartitionRowAsync(pkey, rkey);
})).Where(x => x != null).ToList();
var toInsert = toDelete
.Select(x => AtsOrganizationUserEventByMinute.FromBase(x.OrganizationId, x.OccurredOn, x.CookieId,
to.CustomerUserId, x))
.ToList();
try
{
await Ats.OrganizationUserEventByMinute.UpsertAsync(toInsert);
await Ats.OrganizationUserEventByMinute.DeleteAsync(toDelete);
}
catch (Exception ex)
{
_logger.Error("Unable to merge {0} AtsOrganizationEvents for org {1}, to customer user {2}: {3}",
toInsert.Count, organizationId, to.CustomerUserId, ex.CompleteMessage());
throw;
}
}
众所周知,Azure存储错误消息毫无用处,谷歌也没有返回任何关于批量删除失败的信息
这在使用本地开发存储和生产中都会失败
有什么想法吗?“操作的意外响应代码:0”基本上意味着批处理中的第一个操作失败。失败操作的索引在抛出的错误中返回,因此用户可以更轻松地转到并更改失败批次中的特定操作 通过捕获StorageException并检查以下内容,您可以获得有关失败请求和错误的更多信息:
exception.RequestInformation.HttpStatusCode
exception.RequestInformation.ExtendedErrorInformation.ErrorCode
exception.RequestInformation.ExtendedErrorInformation.ErrorMessage
我们将考虑在将来更改错误消息,以减少混淆。谢谢你的反馈 在我的例子中,错误得到了解决。 “Microsoft.WindowsAzure.Storage.StorageException:”批处理中的元素0返回了意外的响应代码” 代码片段 table.CreateIfNotExists() 主代码 CloudStorageAccount SA=CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(“SC”)) CloudTableClient tableClient=SA.CreateCloudTableClient() CloudTable=tableClient.GetTableReference(“myWorld”) table.CreateIfNotExists() TableBatchOperation batchOperation=新建TableBatchOperation() batchOperation.Insert(对象)
表.ExecuteBatch(批处理操作) 另一个原因是在键字段中使用了无效字符。如果您在谷歌上搜索此错误消息,可能会错过以下答案: 关键字段中不允许使用的字符 PartitionKey和RowKey属性的值中不允许使用以下字符: 正斜杠(/)字符 反斜杠()字符 数字符号(#)字符 问号(?)字符 从U+0000到U+001F的控制字符,包括: 水平制表符(\t)字符 换行符(\n)字符 回车符(\r)字符 从U+007F到U+009F的控制字符
嗨,肯,你介意分享你的.ForEachParallel()和.ToSegmentedList()代码吗?这看起来很方便。谢谢。请参阅和。谢谢,捕获特定的StorageException使我们能够访问ErrorCode和ErrorMessage,在我的例子中,这解释了问题所在。显然,我的数据不包含唯一键。“400:22:批处理请求包含多个具有相同行键的更改。一个实体在批处理请求中只能出现一次。”
private async Task MergeAtsOrganizationUserEvents(int organizationId, IEnumerable<CustomerUserEvent> fromEvents, CustomerUser to)
{
var toDelete = (await fromEvents.SelectParallel(async fromEvent =>
{
var pkey = AtsOrganizationUserEventByMinute.GetPartitionKey(organizationId, fromEvent.OccurredOn);
var rkey = AtsOrganizationUserEventByMinute.GetRowKey(fromEvent.OccurredOn, fromEvent.CustomerUserEventId);
return await Ats.OrganizationUserEventByMinute.FindByPartitionRowAsync(pkey, rkey);
})).Where(x => x != null).ToList();
var toInsert = toDelete
.Select(x => AtsOrganizationUserEventByMinute.FromBase(x.OrganizationId, x.OccurredOn, x.CookieId,
to.CustomerUserId, x))
.ToList();
try
{
await Ats.OrganizationUserEventByMinute.UpsertAsync(toInsert);
await Ats.OrganizationUserEventByMinute.DeleteAsync(toDelete);
}
catch (Exception ex)
{
_logger.Error("Unable to merge {0} AtsOrganizationEvents for org {1}, to customer user {2}: {3}",
toInsert.Count, organizationId, to.CustomerUserId, ex.CompleteMessage());
throw;
}
}
{
"CookieId":null,
"CustomerUserId":185766,
"CustomerUserEventId":3568687,
"OrganizationId":4190,
"EventName":"event1",
"SessionId":null,
"OccurredOn":"2014-10-20T18:17:09.9971379Z",
"UrlId":null,
"Url":null,
"ReferrerUrlId":null,
"ReferrerUrl":null,
"IsSynthetic":false,
"IpAddress":null,
"PartitionKey":"4190.2014.10.20",
"RowKey":"18.17.3568687",
"Timestamp":"2014-10-20T18:17:11.237+00:00",
"ETag":"W/\\" datetime'2014-10-20T18%3A17%3A11.237Z'\\""
}