У меня периодически возникают проблемы с удалением объектов из таблицы Azure. Это затрагивает только около 1% моих попыток, и если тот же вызов будет повторен позже, он будет работать нормально, но я бы хотел выяснить причину этого! Я погуглил свои пальцы и обнаружил, что отсутствие документации о том, как создать очень надежный код для удаления, вставки и обновления, довольно удивительно ... все это кажется немного неудачным " попробуйте, в большинстве случаев это будет работать "
РЕДАКТИРОВАТЬ: Я удаляю текст, который был первоначально в этих вопросах, и заменяю его совершенно новым текстом, чтобы учесть то, что я пытался / что было предложено.
Таблицы Azure подвержены периодическим сбоям, таким как SQL Azure. Если так, то я бы сказал, что "saveChangesWithRetries" справился бы с этим? Это неправильно?
Итак ... довольно просто код, вызываемый примерно 250 раз в минуту на веб-роли Azure. Таблицы Azure используются как часть системы обмена сообщениями. Сообщения вставляются одним пользователем, загружаются другим, при успешной загрузке эти сообщения помечаются как прочитанные.
У каждого пользователя есть раздел для непрочитанных сообщений и раздел для прочитанных сообщений. Таким образом, чтобы пометить сообщение как «прочитанное», оно удаляется из непрочитанного раздела и перемещается в раздел чтения.
Из 250 раз, когда этот код вызывается в минуту, я получу от 2 до 10 следующих ошибок в финальном SaveChangesWithRetries (). Внутреннее исключение:
ResourceNotFound
указанный ресурс не существует.
RequestID: 652a3e13-3911-4503-8e49-6fec32a3c044
Время: 2011-09-28Т22: 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. Error.Stage.1: MessageID: 146751012, BoyID: 477296. Произошла ошибка при обработке этого запроса. в Microsoft.WindowsAzure.StorageClient.Tasks.Task 1.get_Result() at Microsoft.WindowsAzure.StorageClient.Tasks.Task
1.ExecuteAndWait () в BenderRestfulService_3_0_5.AzureCloudTable.Message_MarkAsRead (Int32 uid) в ... 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. Error.Stage.2: MessageID: 146751012, BoyID: 477296. Сообщение НЕ было удалено.
Я совершенно сбит с толку. Любой совет с благодарностью !!!
Стивен