gpt4 book ai didi

c# - 为什么 Entity Framework 为 Azure 移动服务表 Controller 生成以下嵌套 SQL

转载 作者:可可西里 更新时间:2023-11-01 03:11:00 25 4
gpt4 key购买 nike

在将 Entity Framework 与 TableController 一起使用时,我正试图弄清 Entity Framework 问题的根源

我创建了以下设置。

  1. 基本的 TodoItem 示例提供了一个新的移动 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;
    }
  2. 普通的 Web API 2 Controller 。

    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 block ,中间有一个 *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 是什么? (它将保持不变,直到我停止并重新启动应用程序,所以我不知道它是特定于 session 、客户端还是数据库上下文)

  • TableController 对 IQueryable 进行这些修改的确切位置在管道中的什么位置?我假设它是在 Query() 方法被调用后通过一些中间件步骤或稍后在请求中的 on executed 属性完成的,但我终究找不到它。

    <

最佳答案

根据您的描述,我做了一些研究,发现 Azure Mobile Server SDK 在 TableControllerConfigProvider.cs 下使用了以下代码行用于为与 QueryableAttribute 相同的操作添加额外的查询相关过滤器用于启用 Controller 操作以支持 OData 查询参数。

controllerSettings.Services.Add(typeof(IFilterProvider), new TableFilterProvider());

注意:额外的过滤器将在您的操作执行后执行并返回 IQueryable

你可以查看 EnableQueryAttribute.cs并发现 OnActionExecuted 会调用 ExecuteQuery 方法并最终调用 ODataQueryOptions.ApplyTo用于将 OData 查询选项($filter、$orderby、$top、$skip 和 $inlinecount 等)应用于给定的 IQueryable

据我了解,Nested SQL 语句是由 OData 组件生成的。调用ODataQueryOptions.ApplyTo后,你的IQueryable被修改,相关的sql语句也被修改。我在我的常规 Web API Controller 中做了一些测试,如下所示,您可以引用它:

请求:

Get http://localhost:58971/api/todoitem?$top=2&$select=Text,Id,Version

在应用 OData 查询选项之前:

enter image description here

应用 OData 查询选项后:

enter image description here

关于c# - 为什么 Entity Framework 为 Azure 移动服务表 Controller 生成以下嵌套 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45300933/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com