ASP.NET Core 中的 ORM 之 Entity Framework (5)

IQueryable 是将 Linq 表达式翻译成 T-SQL 语句之后再向 SQL 服务器发送命令.
IEnumerable 是在调用自己的 Linq 方法之前先从 SQL 服务器取到数据并加载到本地内存中。

生成迁移 SQL 脚本

EF Core 将迁移更新到生产环境可以使用 Script-Migration 命令生成sql脚本,然后到生产数据库执行.

此命令有几个选项。

-From <String> 迁移应是运行该脚本前应用到数据库的最后一个迁移。 如果未应用任何迁移,请指定 0(默认值)。

-To <String> 迁移是运行该脚本后应用到数据库的最后一个迁移。 它默认为项目中的最后一个迁移。

-Idempotent 此脚本仅会应用尚未应用到数据库的迁移。 如果不确知应用到数据库的最后一个迁移或需要部署到多个可能分别处于不同迁移的数据库,此脚本非常有用。

待补充... SQL 监视工具

有几种方法可以监视 EF Core 自动生成的 SQL 语句:

内置日志

数据库监视工具

Miniprofiler

内置日志: 在调试模式下,EF Core 会使用 ASP.NET Core 的内置日志记录功能把生成的 SQL 语句显示在输出窗口,大概如下:

Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (50ms) [Parameters=[@__get_Item_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [e].[Id], [e].[Rating], [e].[Url] FROM [Blogs] AS [e] WHERE [e].[Id] = @__get_Item_0

如果想查看敏感数据比如@__get_Item_0='?',请在 Context 类的 OnConfiguring 方法里面配置optionsBuilder.EnableSensitiveDataLogging();

数据库监视工具: 也可以通过数据库的监视工具,比如用于监视 MS SQL 的工具 SQL Server Profiler 查看执行的 SQL 语句,大概如下:

exec sp_executesql N'SELECT TOP(1) [e].[Id], [e].[Rating], [e].[Url] FROM [Blogs] AS [e] WHERE [e].[Id] = @__get_Item_0',N'@__get_Item_0 int',@__get_Item_0=1

Miniprofiler: MiniProfiler/dotnet是一款简单而有效的性能分析的轻量级程序,可以监控页面,也可以监控 EF Core 执行的 SQL 语句。

MiniProfiler 一般用于 MVC 项目,但也可以结合 Swagger 用于 Web API项目。Swagger 的安装和使用在本篇不做讨论,详细请参考Swashbuckle.AspNetCore。

Nuget 安装 MiniProfiler 引用

Install-Package MiniProfiler.AspNetCore.Mvc Install-Package MiniProfiler.EntityFrameworkCore

修改 SwaggerUI/index.html 页面: 在项目下面新建一个文件 SwaggerIndex.html 并复制以下代码,设置编译为 Embedded resource

<script async="async" src="http://www.likecs.com/profiler/includes.min.js?v=4.0.138+gcc91adf599" data-version="4.0.138+gcc91adf599" data-path="/profiler/" data-current-id="4ec7c742-49d4-4eaf-8281-3c1e0efa748a" data-ids="" data-position="Left" data-authorized="true" data-max-traces="15" data-toggle-shortcut="Alt+P" data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync"></script> <!-- HTML for static distribution bundle build --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>%(DocumentTitle)</title> <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700"> <link type="text/css" href="http://www.likecs.com/swagger-ui.css"> <link type="image/png" href="http://www.likecs.com/favicon-32x32.png" sizes="32x32" /> <link type="image/png" href="http://www.likecs.com/favicon-16x16.png" sizes="16x16" /> <style> html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; } *, *:before, *:after { box-sizing: inherit; } body { margin: 0; background: #fafafa; } </style> %(HeadContent) </head> <body> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <symbol viewBox="0 0 20 20"> <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path> </symbol> <symbol viewBox="0 0 20 20"> <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z" /> </symbol> <symbol viewBox="0 0 20 20"> <path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z" /> </symbol> <symbol viewBox="0 0 20 20"> <path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z" /> </symbol> <symbol viewBox="0 0 20 20"> <path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z" /> </symbol> <symbol viewBox="0 0 24 24"> <path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" /> </symbol> <symbol viewBox="0 0 24 24"> <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" /> </symbol> </defs> </svg> <div></div> <!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 --> <script> if (window.navigator.userAgent.indexOf("Edge") > -1) { console.log("Removing native Edge fetch in favor of swagger-ui's polyfill") window.fetch = undefined; } </script> <script src="http://www.likecs.com/swagger-ui-bundle.js"></script> <script src="http://www.likecs.com/swagger-ui-standalone-preset.js"></script> <script> window.onload = function () { var configObject = JSON.parse('%(ConfigObject)'); var oauthConfigObject = JSON.parse('%(OAuthConfigObject)'); // Apply mandatory parameters configObject.dom_id = "#swagger-ui"; configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset]; configObject.layout = "StandaloneLayout"; // If oauth2RedirectUrl isn't specified, use the built-in default if (!configObject.hasOwnProperty("oauth2RedirectUrl")) configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html"); // Build a system const ui = SwaggerUIBundle(configObject); // Apply OAuth config ui.initOAuth(oauthConfigObject); } </script> </body> </html> <ItemGroup> <EmbeddedResource Include="SwaggerIndex.html" /> </ItemGroup>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgffdz.html