我想跟踪将由针对
Microsoft.WindowsAzure.StorageClient.TableServiceContext
对象执行的 LINQ 查询生成的 Uri。 TableServiceContext
只是扩展了 System.Data.Services.Client.DataServiceContext
几个属性。
我遇到的问题是,当我们在调试模式下在开发机器上运行 Web 角色时,查询对我们的 Azure 表存储实例执行良好(我们正在连接到云中的 Azure 存储,而不是使用 Dev Storage)。我可以使用 Fiddler 或将鼠标悬停在调试器中的语句上来获取结果查询 Uri。
但是,当我们将 Web 角色部署到 Azure 时,针对完全相同的 Azure 表存储源的查询失败并出现 ResourceNotFound DataServiceClientException。在处理
FirstOrDefault()
在空表上的行为之前,我们遇到过 ResoureNotFound 错误。这不是这里的问题。
作为解决该问题的一种方法,我想比较部署 Web 角色时生成的查询 Uri 与在开发机器上运行时生成的查询 Uri。
有谁知道一种方法来获取调用
FirstOrDefault()
方法时将发送的查询的查询 Uri。我知道您可以在 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
...
}
}
史蒂夫提供了书面答案。我们的问题与此 post 中描述的完全一致,它描述了单一实体查询中 PartitionKey/RowKey 排序的问题,该问题已通过 Azure OS 的更新得到修复。这解释了我们的开发机器与 Web 角色部署到 Azure 的时间之间的差异。
当我指出我们之前在存在性检查中处理过 ResourceNotFound 问题时,我们在代码中以两种方式处理了它。一种方法是使用异常处理来处理 ResourceNotFound 错误,另一种方法是将 RowKey 放在 LINQ 查询中的第一位(正如一些 MS 人员指出的那样)。
事实证明,我们有几个地方首先使用 RowKey 而不是使用异常处理。我们将通过重构我们的代码以针对 .NET 4 并使用
.IgnoreResourceNotFoundException = true property of the
TableServiceContext 来解决这个问题。
经验教训(不止一次):不要依赖古怪的无证行为。
我们能够得到查询 Uri 的。结果确实不同(正如博客文章中指出的那样)。以下是结果:
`https://ourproject.table.core.windows.net/Somethings()?$filter=(RowKey eq '[email protected]') 和 (PartitionKey eq '41e0c1ae-e74d-458e-8a93-d2972d9ea53c')
`https://ourproject.table.core.windows.net/Somethings(RowKey='[email protected]',PartitionKey='41e0c1ae-e74d-458e-8a93-d2972d9ea53c')
我可以做得更好……我想我知道问题出在哪里。 :)
见链接。
具体来说,以前的情况(在以前的来宾操作系统构建中)如果您像以前那样编写查询(在 PartitionKey 谓词之前使用 RowKey 谓词),它会导致筛选查询(相反,PartitionKey 在 RowKey 之前) 导致如果结果集为空则引发异常的查询类型。
我认为适合您的正确解决方法(如上面的博文所示)是在您的上下文中将 IgnoreResourceNotFoundException 设置为 true。