{"id":405866,"date":"2023-11-20T14:37:55","date_gmt":"2023-11-20T13:37:55","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=dotnet&#038;p=405866"},"modified":"2024-02-27T19:57:29","modified_gmt":"2024-02-27T18:57:29","slug":"visualize-entity-framework-relationships-and-additional-query-analysis-in-resharper-2023-3","status":"publish","type":"dotnet","link":"https:\/\/blog.jetbrains.com\/zh-hans\/dotnet\/2023\/11\/20\/visualize-entity-framework-relationships-and-additional-query-analysis-in-resharper-2023-3","title":{"rendered":"Visualize Entity Framework Relationships and Additional Query Analysis in ReSharper 2023.3"},"content":{"rendered":"\n<p>A lot of teams are using Entity Framework or EF Core to work with their database. As an Object-Relational Mapper (ORM), it bridges objects in code to a relational database model, so that as a developer you don\u2019t have to worry too much about the actual database.<\/p>\n\n\n\n<p>We all know: that\u2019s not entirely true. Even with Entity Framework and EF Core, you still <a href=\"https:\/\/blog.jetbrains.com\/zh-hans\/dotnet\/2021\/02\/24\/entity-framework-core-5-pitfalls-to-avoid-and-ideas-to-try#forgetting-to-add-indexes\">have to add indexes<\/a> so data can be retrieved quickly, <a href=\"https:\/\/blog.jetbrains.com\/zh-hans\/dotnet\/2023\/03\/02\/optimizing-entity-framework-core-database-queries-with-dynamic-program-analysis\">be wary about the N+1 problem<\/a>, and many other potential pitfalls.<\/p>\n\n\n\n<p>The latest ReSharper 2023.3 comes with a number of tools and inspections to help you catch potential issues with Entity Framework and EF Core, including a way to generate an Entity Relationship Diagram (ERD) for your database context. Let\u2019s have a look.<\/p>\n\n\n    <div class=\"buttons\">\n        <div class=\"buttons__row\">\n                                                <a href=\"https:\/\/www.jetbrains.com\/resharper\/\" class=\"btn\" target=\"\" rel=\"noopener\">Download ReSharper and try it out!<\/a>\n                                                    <\/div>\n    <\/div>\n\n\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Entity Relationship Diagram<\/h2>\n\n\n\n<p>The most visual update in ReSharper 2023.3 is the new Entity Relationship Diagram (ERD) that you can use to inspect how entities are related to each other. When you open any entity that is part of an Entity Framework or EF Core database context in the editor, you will see that ReSharper identifies it as such:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"88\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/11\/image-20.png\" alt=\"\" class=\"wp-image-405900\"\/><\/figure>\n\n\n\n<p>When you press <strong>Alt+Enter<\/strong>, you can then use the <strong>Show Entity Relationship Diagram<\/strong> action to generate an ERD for the current database context. Clicking the database icon also works, and there\u2019s the <strong>ReSharper | Architecture | Show Entity Relationship Diagram<\/strong> menu as well.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1400\" height=\"428\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/11\/image-17.png\" alt=\"\" class=\"wp-image-405867\"\/><\/figure>\n\n\n\n<p>ReSharper generates a graphic representation of the database model and the relationships between entities, including one-to-one, one-to-many and many-to-many relationships. You can pan and zoom, and look at the various entities in your database context.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1506\" height=\"1092\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/11\/image-18.png\" alt=\"\" class=\"wp-image-405878\"\/><\/figure>\n\n\n\n<p>The diagram also highlights string properties with unlimited length. A perfect segue to the next section!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Unlimited string length inspection<\/h2>\n\n\n\n<p>One of the new inspections introduced in ReSharper 2023.3 analyzes your database context and its entities for properties that have unlimited string length, and highlights them:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1400\" height=\"238\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/11\/image-19.png\" alt=\"\" class=\"wp-image-405889\"\/><\/figure>\n\n\n\n<p>To fix this inspection, you can add a <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.componentmodel.dataannotations.stringlengthattribute\" target=\"_blank\" rel=\"noopener\"><code>[StringLength]<\/code><\/a> or <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.componentmodel.dataannotations.maxlengthattribute\" target=\"_blank\" rel=\"noopener\"><code>[MaxLength]<\/code><\/a> attribute to specify the length of the string in the database model. Alternatively, you can use the <code>HasMaxLength()<\/code> builder method in your database context model creation logic:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"wpcustom\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class Database : DbContext\n{\n    \/\/ ...\n\n    protected override void OnModelCreating(ModelBuilder builder)\n    {\n        \/\/ Country\n        builder.Entity&lt;Country>().Property(ci => ci.Name)\n            .HasMaxLength(100);\n    }\n}\n<\/pre>\n\n\n\n<p>In SQL Server and Azure SQL Database, an unbounded string with unlimited length will be stored in a <code>nvarchar(max)<\/code> column. When you know the data will never exceed a certain length, limiting the string length in your EF model will translate into the data being stored in an <code>nvarchar(N)<\/code> column.<\/p>\n\n\n\n<p>Now, why does this matter? By default, <a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/pages-and-extents-architecture-guide\" target=\"_blank\" rel=\"noopener\">SQL Server stores data in pages on disk<\/a> where each row and its data can be 8060 bytes in size. Large object data types (LOB) such as <code>xml<\/code>, <code>varbinary(max)<\/code>, and <code>varchar(max)<\/code>, are stored in a separate location in SQL Server. When a row is too large (or has many LOBs), SQL Server can not read data in one go and has to look in several places to filter and return the result set for your query, resulting in additional I\/O overhead.<\/p>\n\n\n\n<p>In MySQL and MariaDB, <a href=\"https:\/\/docs.oracle.com\/cd\/E17952_01\/mysql-5.7-en\/innodb-limits.html#:~:text=Although%20InnoDB%20supports%20row%20sizes,must%20be%20less%20than%202GB.\" target=\"_blank\" rel=\"noopener\">row size is constrained to 65535 bytes<\/a>, so limiting how long a row can get is crucial to keeping your database and its performance happy!<\/p>\n\n\n\n<p><strong>The new <em>unlimited string length<\/em> inspection helps you discover properties that have the potential to impact database performance<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">DbFunction inspections<\/h2>\n\n\n\n<p>Another new inspection helps detect usages of methods in Entity Framework-related code that could potentially produce runtime exceptions. Whenever you use a function that is not convertible to SQL, ReSharper will let you know about this.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"377\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/11\/image-21.png\" alt=\"\" class=\"wp-image-405911\"\/><\/figure>\n\n\n\n<p>Additionally, when using methods that are only to be used in a database context, such as functions in the <code>EF.Functions<\/code> property, ReSharper informs you that the <strong>database function must not be called in non-database context<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1600\" height=\"418\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/11\/image-22.png\" alt=\"\" class=\"wp-image-405922\"\/><\/figure>\n\n\n\n<p>These 2 new inspections will make sure that potential exceptions in executing (non-)database queries are discovered even before running your application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">In conclusion<\/h2>\n\n\n\n<p>Being able to inspect the relationships between entities in an Entity Relationship Diagram (ERD) is a great opportunity for finding missing relationships or dependency loops in a graphical way.&nbsp;<\/p>\n\n\n\n<p>Combined with the ability to find properties that may negatively impact query performance, and to find usages of functions that do not belong in an Entity Framework query, this ReSharper release will help you build more solid applications using Entity Framework and EF Core.&nbsp;<\/p>\n\n\n\n<p>And of course, don\u2019t forget the <a href=\"https:\/\/blog.jetbrains.com\/zh-hans\/dotnet\/2023\/09\/21\/eager-lazy-and-explicit-loading-with-entity-framework-core\">Entity Framework and EF Core N+1 inspections<\/a> introduced in the previous ReSharper and JetBrains Rider releases!<\/p>\n\n\n\n<p>What do you think of the new ERD and inspections? Let us know in the comments!<\/p>\n","protected":false},"author":118,"featured_media":405933,"comment_status":"closed","ping_status":"closed","template":"","categories":[4992,1401],"tags":[118,6927,46,1978],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/405866"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/dotnet"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/118"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=405866"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/405866\/revisions"}],"predecessor-version":[{"id":449341,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/405866\/revisions\/449341"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/405933"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=405866"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=405866"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=405866"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=405866"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}