16

Azureのモバイルサービス表コントローラの次のネストされたSQLを生成するEntity Frameworkのです。は、なぜ私は次のセットアップを作成しました<code>TableController</code></p> <p>でそれを使用した場合、エンティティフレームワークの問題の底に取得しようとしている

  1. 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. バニラウェブAPI 2コントローラを活用し、新たなモバイルWeb APIを備えた基本的なTodoItem例。私はちょうどIQueryable

    Where(_ => !_.IsDeleted)変更で追加するDomainManager経由でコールをプロキシさQuery方法、掘り下げる、細かい歯の櫛でtablecontrollerコードを行ってきた

    public class TodoItemsWebController : ApiController 
    { 
    
        private MobileServiceContext db = new MobileServiceContext(); 
        public TodoItemsWebController() 
        { 
         db.Database.Log += LogToDebug; 
        } 
    
        public IQueryable<TodoItem> GetTodoItems() 
        { 
         return db.TodoItems; 
        } 
    

しかし、2つのクエリは非常に異なるSQLを生成します。

通常のWeb APIコントローラでは、次の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については、次のそれの真ん中に*マジック* GUIDを持つSQLのチャンク、およびネストされたSQL文で結果を取得します。 $ top、$ skip、$ filter、$ expandのようなODATAv3クエリのいずれかを扱うときに、この処理が完了するとゴミが出ます。

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とは何ですか? (アプリケーションを停止して再起動してセッションやクライアント、DBのコンテキストがわからないので、アプリケーションを停止して再起動するまでは同じままです) Query()メソッドが呼び出された後に、要求の後半でミドルウェアのステップまたは実行された属性によって実行されたと見なしますが、私の人生にとってはそれを見つけることができません。

+0

これは、Odataクエリを実装するモバイルサーバーSDKに関連していると思います。私がvar items = Query()。ToList()を使用すると、SQLクエリがWeb APIのように正しいことがわかりました。しかし、我々はOdataクエリを使用することができませんでした。 –

+0

これは本当にオプションではありませんが、クライアントコンシューマはOdata $ varsの使用に依存するためです。例えば初期ロード時には '$ top'と' $ skip'を使用して、APIの呼び出しを行い、最初のDB Syncを実行します。 –

+0

これは、EntityDomainManagerが並行性チェックのために各行と共にフィールドの値をダウンロードして保持するためです。 GuidはソースからのETAGの一種ですhttps://github.com/Azure/azure-mobile-apps-net-server/blob/master/src/Microsoft.Azure.Mobile.Server.Entity/EntityDomainManager.cs –

答えて

1

テーブルの1つがバックエンドとクライアントの間で同期されているため、2番目のSQLが取得されているためです。

はもっとここで読む:あなたの説明によると、私はいくつかの研究を行なったし、QueryableAttributeと同じアクションのために追加のクエリに関連するフィルタを追加するためのAzure MobileサーバーSDKはTableControllerConfigProvider.csの下に次のコード行を使用していることを見つけhttps://documentation.devexpress.com/wpf/17927/Common-Concepts/Scaffolding-Wizard/Tutorials/Building-Outlook-Inspired-and-Hybrid-UI-Applications/Lesson-3-Customize-Layout-of-the-Collection-Views

5

コントローラアクションがODataクエリパラメータをサポートできるようにします。

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

注:追加のフィルタは、あなたのアクションが実行された後に実行してIQueryableを返すことになります。

あなたはEnableQueryAttribute.csをチェックし、OnActionExecutedExecuteQueryメソッドを呼び出して、最終的にのODataクエリオプションを適用するためのODataQueryOptions.ApplyToを呼ぶだろうことを発見できたIQueryable与えに($、$フィルタ、$のORDERBY、$トップをスキップし、inlinecount $など) 。

私の理解しているように、ネストされたSQL文はODataコンポーネントによって生成されます。 ODataQueryOptions.ApplyToが呼び出された後、IQueryableが変更され、関連するSQL文も変更されました。私は次のように、あなたはそれを参照することができ、私の通常のWeb APIコントローラーでいくつかのテストをしました:

要求:

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

のODataクエリオプションを適用する前に:

enter image description here

ODataクエリオプションを適用した後:

enter image description here

関連する問題

 関連する問題