我在从天蓝色表中删除对象时遇到间歇性问题。它只影响我大约 1% 的尝试,如果稍后再次进行相同的调用,那么它工作正常,但我很想找出背后的原因!我在谷歌上搜索了一下,发现缺乏关于如何创建非常可靠的删除、插入和更新代码的文档,这令人非常惊讶……这一切似乎有点碰运气,”尝试一下,大多数时候都会有效”
编辑:我正在删除这个问题中最初的文本,并将其替换为全新的文本,以考虑我已经尝试/建议的内容。
Azure 表是否会像 SQL Azure 一样遭受间歇性故障。如果是这样,我会认为“saveChangesWithRetries”会处理这个问题吗?这是错误的吗?
所以...相当简单的代码,在 Azure Web 角色上每分钟被调用大约 250 次。天蓝色表用作消息传递系统的一部分。消息由一个用户插入,由另一个用户下载,成功下载后,这些消息将被标记为已读。
每个用户都有一个未读消息分区和已读消息分区。因此,要将消息标记为“已读”,请将其从未读分区中删除并移动到已读分区中。
在每分钟调用此代码 250 次的情况下,我将在最终的 SaveChangesWithRetries() 中收到 2 到 10 个以下错误。内部异常是:
ResourceNotFound
这
指定的资源不存在。
请求ID:652a3e13-3911-4503-8e49-6fec32a3c044
时间:2011-09-28T22:09:39.0795651Z
我不认为单个分区每分钟被访问的次数不会超过几次。
这是我的代码:
public static void Message_MarkAsRead(int uid)
{
try
{
storageAccount = CloudStorageAccount.Parse(connectionString);
tableClient = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
tableClient.RetryPolicy = RetryPolicies.Retry(retryAmount, TimeSpan.FromSeconds(retrySeconds));
TableServiceContext tableServiceContext = tableClient.GetDataServiceContext();
tableServiceContext.IgnoreResourceNotFoundException = true;
//the messageUserJoinerTable let's us join messageId to userFromId and userToId
//each message is inserted into the tables twice, once into the userFromId partition and also into the userToId partition
#region get the userToId and userFromId for this message uid
List<int> userIds = new List<int>();
var resultsUserIds = from messagesUserJoinerTable in tableServiceContext.CreateQuery<MessageUserJoinerDataEntity>(messageUserJoinerTableName)
where messagesUserJoinerTable.PartitionKey == uid.ToString()
select messagesUserJoinerTable;
foreach (MessageUserJoinerDataEntity messageUserJoiner in resultsUserIds)
{
userIds.Add(messageUserJoiner.UserId);
}
#endregion
#region then we need to check the partition for each of these users and mark the messages as read
if (userIds.Count > 0)
{
foreach (int userId in userIds)
{
var resultsUnreadMessages = from messagesTable in tableServiceContext.CreateQuery<MessageDataEntity>(messageTableName)
where messagesTable.PartitionKey == CreatePartitionKey(userId, false)
&& messagesTable.RowKey == CreateRowKey(uid)
select messagesTable;
//there should only ever be one as duplicate partition/rowkey is not allowed
MessageDataEntity messageUnread = resultsUnreadMessages.FirstOrDefault();
if (messageUnread != null)
{
bool isUnreadMessageDeleted = false;
//shallow copy the message for re-inserting as read
MessageDataEntity messageRead = new MessageDataEntity(messageUnread);
//delete the message
try
{
tableServiceContext.Detach(messageUnread);
tableServiceContext.AttachTo(messageTableName, messageUnread, "*");
tableServiceContext.DeleteObject(messageUnread);
//this is where the error occurs
tableServiceContext.SaveChangesWithRetries();
isUnreadMessageDeleted = true;
}
catch (Exception ex)
{
MyTrace.Trace("AzureCloudTable_" + Service.versionForTracing + ".Message_MarkAsRead. Error.Stage.1: MessageID:" + uid + ", UserID:" + userId + ". " + ex.Message + ex.StackTrace + ", " + ex.InnerException.Message + ex.InnerException.StackTrace, "Error. MarkAsRead");
//check to see if the message we tried to delete has already been deleted
//if so, we just consume this error and continue by inserting the read message
//else, we throw the exception outwards
var resultsUnreadMessagesLastCheck = from messagesTable in tableServiceContext.CreateQuery<MessageDataEntity>(messageTableName)
where messagesTable.PartitionKey == CreatePartitionKey(userId, false)
&& messagesTable.RowKey == CreateRowKey(uid)
select messagesTable;
//there should only ever be one as duplicate partition/rowkey is not allowed
MessageDataEntity messageUnreadLastCheck = resultsUnreadMessages.FirstOrDefault();
if (messageUnreadLastCheck != null)
{
MyTrace.Trace("AzureCloudTable_" + Service.versionForTracing + ".Message_MarkAsRead. Error.Stage.2: MessageID:" + uid + ", UserID:" + userId + ". Message WAS deleted.", "Error. MarkAsRead");
//the message IS deleted, so although I don't understand why getting error in the first
//place, the result should be the same
throw ex;
}
else
{
//the message is NOT deleted, so we may as well give up now as I don't understand
//what's going on
MyTrace.Trace("AzureCloudTable_" + Service.versionForTracing + ".Message_MarkAsRead. Error.Stage.2: MessageID:" + uid + ", UserID:" + userId + ". Message was NOT deleted.", "Error. MarkAsRead");
}
}
//mark the new message as read
if (isUnreadMessageDeleted)
{
messageRead.PartitionKey = CreatePartitionKey(userId, true);
messageRead.IsRead = true;
//check if read message already exists in storage, if not, insert
var resultsReadMessages = from messagesTable in tableServiceContext.CreateQuery<MessageDataEntity>(messageTableName)
where messagesTable.PartitionKey == CreatePartitionKey(userId, true)
&& messagesTable.RowKey == CreateRowKey(uid)
select messagesTable;
//do the insert
if (resultsReadMessages.FirstOrDefault() == null)
{
tableServiceContext.AddObject(messageTableName, messageRead);
tableServiceContext.SaveChangesWithRetries();
}
}
}
}
}
#endregion
}
catch (Exception ex)
{
try
{
MyTrace.Trace("AzureCloudTable_" + Service.versionForTracing + ".Message_MarkAsRead. Error: " + ex.Message + ex.StackTrace + ", " + ex.InnerException.Message + ex.InnerException.StackTrace, "Error. MarkAsRead");
}
catch (Exception)
{
MyTrace.Trace("AzureCloudTable_" + Service.versionForTracing + ".Message_MarkAsRead. Error: " + ex.Message + ex.StackTrace, "Error. MarkAsRead");
}
}
}
我不明白当资源作为查询的一部分返回给我,然后我对其进行了 != null 检查时,资源怎么可能不存在。
根据之前的回复,我添加了代码来在尝试中进行额外的检查,以查看该对象是否已被以某种方式删除。尚未删除
我的跟踪在出现错误时返回此信息:
AzureCloudTable_3_0_5.Message_MarkAsRead。错误.阶段 1:消息 ID:146751012,男孩 ID:477296。处理此请求时发生错误。在 Microsoft.WindowsAzure.StorageClient.Tasks.Task1.get_Result() at Microsoft.WindowsAzure.StorageClient.Tasks.Task
1.BenderRestfulService_3_0_5.AzureCloudTable.Message_MarkAsRead(Int32 uid) 处的 ExecuteAndWait() ...ResourceNotFound
指定的资源不存在。 RequestId:583c59df-fdac-47e4-a03c-7a4bc7d004c9 时间:2011-10-05T16:37:36.7940530Z 在 System.Data.Services.Client.DataServiceContext.SaveResult.d__1e.MoveNext()
AzureCloudTable_3_0_5.Message_MarkAsRead。错误.阶段 2:消息 ID:146751012,男孩 ID:477296。消息未被删除。
我完全困惑了。任何建议都非常感谢!
Steven