Определить запрос Uri из запроса LINQ служб данных WCF для FirstOrDefault для Azure, не выполняя его? - PullRequest
1 голос
/ 27 июля 2010

Проблема

Я бы хотел отследить Uri, который будет сгенерирован запросом LINQ, выполненным для объекта Microsoft.WindowsAzure.StorageClient.TableServiceContext.TableServiceContext просто расширяет System.Data.Services.Client.DataServiceContext парой свойств.

Проблема, с которой я сталкиваюсь, заключается в том, что запрос отлично выполняется для нашего экземпляра хранилища таблиц Azure, когда мы запускаем веб-роль на компьютере разработчика в режиме отладки.(мы подключаемся к хранилищу Azure в облаке, не используя Dev Storage).Я могу получить итоговый запрос Uri, используя Fiddler или просто наведя указатель мыши на оператор в отладчике.

Однако при развертывании веб-роли в Azure запрос завершается неудачно для того же источника хранилища таблиц Azure с * 1010.* ResourceNotFound DataServiceClientException .До этого у нас были ошибки ResoureNotFound, связанные с поведением FirstOrDefault() в пустых таблицах.Здесь проблема не в этом.

В качестве одного из подходов к этой проблеме я хотел сравнить Uri запроса, который генерируется при развертывании веб-роли, и когда он выполняется на компьютере разработчика.

Вопрос

Кто-нибудь знает способ получить 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
        ...
    }
}

Редактировать обновление и ответ

Стив предоставилнапиши ответ.Наша проблема была точно описана в этом посте , в котором описана проблема с упорядочением PartitionKey / RowKey в запросе Single Entity , которая была исправлена ​​с обновлением ОС Azure.Это объясняет несоответствие между нашими компьютерами и тем, когда веб-роль была развернута в Azure.

Когда я указывал, что мы уже сталкивались с проблемой ResourceNotFound ранее в наших проверках существования, мы имели дело сэто двумя способами в нашем коде.Одним из способов было использование обработки исключений, чтобы справиться с ошибкой ResourceNotFound , а другой путь состоял в том, чтобы поставить RowKey первым в запросе LINQ (как указали некоторые сотрудники MS, было уместно).*

Оказывается, у нас есть несколько мест, где RowKey был первым вместо использования обработки исключений.Мы решим эту проблему путем рефакторинга нашего кода для целевой платформы .NET 4 и использования .IgnoreResourceNotFoundException = true property of the TableServiceContext.

Извлеченный урок (более одного раза): не зависит от странного недокументированного поведения.

Помимо

Нам удалось получить запрос Ури.Они оказались разными (как указано, они будут в блоге).Вот результаты:

Запрос Uri от Dev Fabric

`https://ourproject.table.core.windows.net/Somethings()?$filter=(RowKey eq 'test19@gmail.com') и (PartitionKey eq '41e0c1ae-e74d-458e-8a93-d2972d9ea53c ')

Запрос Uri из Azure Fabric

`https://ourproject.table.core.windows.net/Somethings(RowKey='test19@gmail.com',PartitionKey='41e0c1ae-e74d-458e-8a93-d2972d9ea53c')

1 Ответ

2 голосов
/ 27 июля 2010

Я могу сделать лучше ... Думаю, я знаю, в чем проблема. :)

См. http://blogs.msdn.com/b/windowsazurestorage/archive/2010/07/26/how-wcf-data-service-changes-in-os-1-4-affects-windows-azure-table-clients.aspx.

В частности, раньше (в предыдущих сборках гостевой ОС), когда вы писали запрос, как вы делали (с предикатом RowKey перед предикатом PartitionKey), это приводило к запросу фильтра (в то время как наоборот, PartitionKey предшествующий RowKey) привел к виду запроса, который вызывает исключение, если набор результатов пуст.

Я думаю, что правильное решение для вас (как указано в сообщении блога выше) - установить для IgnoreResourceNotFoundException значение true в вашем контексте.

...