Я хотел бы проследить Uri, который будет сгенерирован запросом LINQ, выполняемым против a Microsoft.WindowsAzure.StorageClient.TableServiceContext
объект. TableServiceContext
просто расширяется System.Data.Services.Client.DataServiceContext
с несколькими свойствами.
Проблема, которую я имею, - то, что запрос выполняется прекрасный против нашего Экземпляра ресурса хранения Таблицы Azure, когда мы выполняем веб-роль на dev машине в режиме отладки (мы соединяемся с устройством хранения данных Azure в облаке, не использующем устройство хранения данных Dev). Я могу получить получающийся запрос Uri, использующий Скрипача или просто нависающий над оператором в отладчике.
Однако, когда мы развертываем веб-роль на Azure сбои запроса против той же самой Azure источник устройства хранения данных Таблицы с ResourceNotFound DataServiceClientException. У нас были ошибки ResoureNotFound, прежде чем это имело дело с поведением FirstOrDefault()
на пустых таблицах. Это не проблема здесь.
Как один подход к проблеме, я хотел сравнить запрос Uri, который сгенерирован, когда веб-роль развертывается по сравнению с тем, когда это работает на dev машине.
Делает любой знает способ получить запрос Uri для запроса, который будет отправлен когда FirstOrDefault()
метод называют. Я знаю, что можно звонить ToString()
на IQueryable
возвращенный из TableServiceContext
но мое беспокойство - это когда FirstOrDefault()
назван Uri мог бы быть далее оптимизирован и ToString()
на IQueryable
не мог бы быть тем, что в конечном счете отправляется на сервер когда FirstOrDefault()
назван.
Если у кого-то есть другой подход к проблеме, я открыт для предложений. Это, кажется, общая проблема с LINQ при попытке определить то, что произойдет, когда дерево выражений будет наконец оценено. Я открыт для предложений здесь также, потому что мои навыки LINQ могли использовать некоторое улучшение.
public void AddSomething(string ProjectID, string Username) {
TableServiceContext context = new TableServiceContext();
var qry = context.Somethings.Where(m => m.RowKey == Username
&& m.PartitionKey == ProjectID);
System.Diagnostics.Trace.TraceInformation(qry.ToString());
// ^ Here I would like to trace the Uri that will be generated
// and sent to the server when the qry.FirstOrDefault() call below is executed.
if (qry.FirstOrDefault() == null) {
// ^ This statement generates an error when the web role is running
// in the fabric
...
}
}
Steve предоставил ответ записи. Наша проблема была как точно описана в этом сообщении, которое описывает проблему с PartitionKey/RowKey, заказывающим в Единственном запросе Объекта, который был зафиксирован с обновлением Azure ОС. Это объясняет несоответствие между нашими dev машинами и когда веб-роль была развернута на Azure.
Когда я указал, что мы занимались проблемой ResourceNotFound прежде в наших проверках существования, мы имели дело с нею двумя способами в нашем коде. Один путь использовал обработку исключений для контакта с ошибкой ResourceNotFound, другой путь состоял в том, чтобы поместить RowKey сначала в запрос LINQ (как некоторые люди MS указали, было соответствующим).
Оказывается, что у нас есть несколько мест, где RowKey был первым вместо того, чтобы использовать обработку исключений. Мы обратимся к этому путем рефакторинга нашего кода для предназначения для.NET 4 и использования .IgnoreResourceNotFoundException = true property of the
TableServiceContext.
Урок извлечен (несколько раз): не зависьте от изворотливого недокументированного поведения.
Мы смогли получить запрос Uri. Они действительно оказывались отличающимися (как обозначено, они будут в сообщении в блоге). Вот результаты:
'https://ourproject.table.core.windows.net/Somethings ()? $filter = ('test19@gmail.com' RowKey eq) и (PartitionKey eq '41e0c1ae-e74d-458e-8a93-d2972d9ea53c')
'https://ourproject.table.core.windows.net/Somethings (RowKey ='test19@gmail.com', PartitionKey = '41e0c1ae-e74d-458e-8a93-d2972d9ea53c')
Я могу сделать еще лучше ... Думаю, я знаю, в чем проблема. :)
В частности, раньше (в предыдущих сборках гостевой ОС), если вы написали запрос, как вы это делали (с предикатом RowKey перед предикатом PartitionKey), это приводило к запросу фильтра (в то время как обратное, PartitionKey предшествующий RowKey) привел к типу запроса, который вызывает исключение, если набор результатов пуст.
Я думаю, что правильное решение для вас (как указано в сообщении в блоге выше) - это установить для IgnoreResourceNotFoundException значение true в вашем контексте.