[英]Why is Entity Framework generating the following nested SQL for Azure Mobile Services Table Controllers
在将它与TableController
一起使用时,我试图找到实体框架问题的底部
我创建了以下设置。
基本的TodoItem示例提供了一个新的Mobile Web API,它利用了EntityFramework,TableController和默认的EntityDomainManager
public class TodoItemController : TableController<TodoItem> { protected override void Initialize(HttpControllerContext controllerContext) { base.Initialize(controllerContext); context = new MobileServiceContext(); context.Database.Log += LogToDebug; DomainManager = new EntityDomainManager<TodoItem>(context, Request); } public IQueryable<TodoItem> GetAllTodoItems() { var q = Query(); return q; }
一个vanilla Web API 2控制器。
public class TodoItemsWebController : ApiController { private MobileServiceContext db = new MobileServiceContext(); public TodoItemsWebController() { db.Database.Log += LogToDebug; } public IQueryable<TodoItem> GetTodoItems() { return db.TodoItems; }
我已经通过细齿梳子查看了tablecontroller
代码,深入了解了Query
方法,它只是通过DomainManager
代理调用,将Where(_ => !_.IsDeleted)
修改添加到IQueryable
然而,这两个查询产生了非常不同的SQL。
对于常规Web API Controller,您将获得以下SQL。
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Version] AS [Version],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[UpdatedAt] AS [UpdatedAt],
[Extent1].[Deleted] AS [Deleted],
[Extent1].[Text] AS [Text],
[Extent1].[Complete] AS [Complete]
FROM [dbo].[TodoItems] AS [Extent1]
但对于TableController,您将得到以下SQL块,其中间有一个* Magic * Guid,并产生一个嵌套的SQL语句。 当您开始处理任何ODATAv3查询(例如$ top,$ skip,$ filter和$ expand)时,这会完成垃圾的性能。
SELECT TOP (51)
[Project1].[C1] AS [C1],
[Project1].[C2] AS [C2],
[Project1].[C3] AS [C3],
[Project1].[Complete] AS [Complete],
[Project1].[C4] AS [C4],
[Project1].[Text] AS [Text],
[Project1].[C5] AS [C5],
[Project1].[Deleted] AS [Deleted],
[Project1].[C6] AS [C6],
[Project1].[UpdatedAt] AS [UpdatedAt],
[Project1].[C7] AS [C7],
[Project1].[CreatedAt] AS [CreatedAt],
[Project1].[C8] AS [C8],
[Project1].[Version] AS [Version],
[Project1].[C9] AS [C9],
[Project1].[Id] AS [Id]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Version] AS [Version],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[UpdatedAt] AS [UpdatedAt],
[Extent1].[Deleted] AS [Deleted],
[Extent1].[Text] AS [Text],
[Extent1].[Complete] AS [Complete],
1 AS [C1],
N'804f84c6-7576-488a-af10-d7a6402da3bb' AS [C2],
N'Complete' AS [C3],
N'Text' AS [C4],
N'Deleted' AS [C5],
N'UpdatedAt' AS [C6],
N'CreatedAt' AS [C7],
N'Version' AS [C8],
N'Id' AS [C9]
FROM [dbo].[TodoItems] AS [Extent1]
) AS [Project1]
ORDER BY [Project1].[Id] ASC
您可以在此处查看两个查询的结果。 https://pastebin.com/tSACq6eg
所以我的问题是:
为什么TableController
以这种方式生成SQL?
查询中间的* magic * guid是什么? (它将保持不变,直到我停止并重新启动应用程序,因此我不知道它是否是会话,客户端或数据库上下文特定)
TableController究竟在管道中对IQueryable
进行这些修改? 我假设它是在调用Query()
方法之后通过一些中间件步骤或稍后在请求中执行的属性完成的,但我不能在我的生活中找到它。
根据您的描述,我做了一些研究,发现Azure Mobile Server SDK使用TableControllerConfigProvider.cs下的以下代码行为QueryableAttribute添加与相同操作的其他查询相关过滤器,以使控制器操作能够支持OData查询参数。
controllerSettings.Services.Add(typeof(IFilterProvider), new TableFilterProvider());
注意:执行操作后将执行其他过滤器并返回IQueryable
。
您可以检查EnableQueryAttribute.cs并发现OnActionExecuted
将调用ExecuteQuery
方法并最终调用ODataQueryOptions.ApplyTo以将OData查询选项($ filter,$ orderby,$ top,$ skip和$ inlinecount等)应用于给定的IQueryable
。
根据我的理解,嵌套SQL语句由OData组件生成。 在调用ODataQueryOptions.ApplyTo
,您的IQueryable已被修改,并且相关的sql语句也已被修改。 我在常规Web API Controller中做了一些测试,如下所示,你可以参考它:
请求:
Get http://localhost:58971/api/todoitem?$top=2&$select=Text,Id,Version
在应用OData查询选项之前:
应用OData查询选项后:
您的其中一个表在后端和客户端之间同步,因为如果您正在获得第二个sql。
在这里阅读更多内容: https : //documentation.devexpress.com/wpf/17927/Common-Concepts/Scaffolding-Wizard/Tutorials/Building-Outlook-Inspired-and-Hybrid-UI-Applications/Lesson-3-Customize-Layout-的最collection视图
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.