{"id":2090,"date":"2024-03-27T11:41:42","date_gmt":"2024-03-27T11:41:42","guid":{"rendered":"https:\/\/www.mainmind.com\/blog\/?p=2090"},"modified":"2024-03-27T11:42:29","modified_gmt":"2024-03-27T11:42:29","slug":"dbcontext-identity-entity-framework-ef-core-power-tools","status":"publish","type":"post","link":"https:\/\/www.mainmind.com\/blog\/dbcontext-identity-entity-framework-ef-core-power-tools\/","title":{"rendered":"DbContext + (Identity + Entity Framework) + EF Core Power Tools"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Vamos a intentar explicar un escenario de desarrollo en <a href=\"https:\/\/visualstudio.microsoft.com\/es\/downloads\/\" data-type=\"link\" data-id=\"https:\/\/visualstudio.microsoft.com\/es\/downloads\/\">Visual Studio<\/a>, en un modelo de dise\u00f1o que parte de base de datos existente, SQL Server en este caso (<em>Database first<\/em>), en el cual integramos la autenticaci\u00f3n mediante <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/security\/authentication\/identity?view=aspnetcore-8.0&amp;tabs=netcore-cli#create-a-web-app-with-authentication\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/security\/authentication\/identity?view=aspnetcore-8.0&amp;tabs=netcore-cli#create-a-web-app-with-authentication\">ASP.NET Core Identity <\/a>con las tablas ya existentes relacionadas con lo usuarios de Identity; todo ello utilizando un \u00fanico <em>DbContext<\/em>&#8230;<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">Utilizaremos la extensi\u00f3n <a href=\"https:\/\/github.com\/ErikEJ\/EFCorePowerTools\" data-type=\"link\" data-id=\"https:\/\/github.com\/ErikEJ\/EFCorePowerTools\">EF Core Power Tools<\/a> para facilitar convertir nuestras tablas en objetos y clases de nuestra aplicaci\u00f3n, en el ejemplo se realiza con <em>Blazor <\/em>pero servir\u00eda para otro proyecto de .NET diferente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando generamos nuestro DbContext desde la extensi\u00f3n debemos hacerlo heredar de la clase <em>IdentityDbContext<\/em>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Microsoft.AspNetCore.Identity.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace MainMindSpace\n{\n    public class MiContexto : IdentityDbContext&lt;ApplicationUser&gt;\n    {\n    }\n\n    protected override void OnModelCreating(ModelBuilder modelBuilder)\n    {\n        base.OnModelCreating(modelBuilder); \/\/ Llamada al m\u00e9todo base\n\n    }\n    public class ApplicationUser : IdentityUser\n    {\n        \/\/ Puedes agregar propiedades adicionales aqu\u00ed si es necesario\n    }\n}\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ahora bien, si en el proceso de \u00ab<em>Reverse engineer<\/em>\u00bb hemos seleccionado las tablas que genera nuestro modelo Identity, empecer\u00e1n a aparecer errores en tiempo de ejecuci\u00f3n al acceder a nuestro modelo de base de datos:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCannot use table &#039;AspNetUsers&#039; for entity type &#039;AspNetUsers&#039; since it is being used for entity type &#039;ApplicationUser&#039; and potentially other entity types, but there is no linking relationship. Add a foreign key to &#039;AspNetUsers&#039; on the primary key properties and pointing to the primary key on another entity type mapped to &#039;AspNetUsers&#039;.\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">La clase de la que heredamos, ya tiene mapeadas estas tablas, por lo que no debemos a\u00f1adirlas desde EF Core Power Tools:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"406\" height=\"493\" src=\"https:\/\/www.mainmind.com\/blog\/wp-content\/uploads\/2024\/efcpt_db.jpg\" alt=\"efcpt_db sobre 2024\" class=\"wp-image-2091\" srcset=\"https:\/\/www.mainmind.com\/blog\/wp-content\/uploads\/2024\/efcpt_db.jpg 406w, https:\/\/www.mainmind.com\/blog\/wp-content\/uploads\/2024\/efcpt_db-247x300.jpg 247w\" sizes=\"auto, (max-width: 406px) 100vw, 406px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Si tenemos tablas propias que se relacionan con las de la clase heredada, deberemos a\u00f1adir a mano la relaci\u00f3n existente entre ambas, utilizando <a href=\"https:\/\/learn.microsoft.com\/es-es\/ef\/ef6\/modeling\/code-first\/fluent\/types-and-properties\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/es-es\/ef\/ef6\/modeling\/code-first\/fluent\/types-and-properties\">API fluent de Entity Framework<\/a>. Por ejemplo, una tabla \u00abpresupuestos\u00bb con el campo \u00abresponsable\u00bb como clave externa apuntando ApplicationUser.Id (lo que ser\u00eda la tabla AspNetUser.Id)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprotected override void OnModelCreating(ModelBuilder modelBuilder)\n{\n    base.OnModelCreating(modelBuilder);\n\n    modelBuilder.Entity&lt;presupuestos()\n        .HasOne(p =&gt; p.responsableNavigation)\n        .WithMany()\n        .HasForeignKey(p =&gt; p.responsable)   \/\/ La clave externa en presupuestos\n        .HasPrincipalKey(u =&gt; u.Id)          \/\/ La clave principal en ApplicationUser\n        .IsRequired(true);                   \/\/ Si es opcional o no\n\n    \/\/ Otras configuraciones de modelo...\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Se mantiene la nomenclatura a\u00f1adiendo \u00ab<em>Navigation<\/em>\u00bb al campo con la clave externa:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic partial class presupuestos\n{\n    public long id_presupuesto { get; set; }\n    public string? descripcion { get; set; }\n\n    public string responsable { get; set; } = null!;\n    public virtual ApplicationUser responsableNavigation { get; set; } = null!;\n    ...\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">NOTA: en las \u00faltimas versiones de Identity, el Id ha pasado a ser cadena de texto de 450 caracteres, en lugar de Guid o similar. <a href=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/migration\/proper-to-2x\/membership-to-core-identity?view=aspnetcore-6.0\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/en-us\/aspnet\/core\/migration\/proper-to-2x\/membership-to-core-identity?view=aspnetcore-6.0\">Si realizas migraci\u00f3n desde Membership, revisa la documentaci\u00f3n<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Definiendo dentro del m\u00e9todo \u00ab<em>OnModelCreating<\/em>\u00bb logramos que Entity Framework pueda entender correctamente la estructura de la base de datos y pode realizar consultas con datos relacionados.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Vamos a intentar explicar un escenario de desarrollo en Visual Studio, en un modelo de dise\u00f1o que parte de base de datos existente, SQL Server en este caso (Database first), en el cual integramos la autenticaci\u00f3n mediante ASP.NET Core Identity con las tablas ya existentes relacionadas con lo usuarios de Identity; todo ello utilizando un [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1997,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[958,956,957,724,959],"class_list":["post-2090","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-studio","tag-database-first","tag-dbcontext","tag-ef-core-power-tools","tag-entity-framework","tag-identitydbcontext"],"_links":{"self":[{"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/posts\/2090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/comments?post=2090"}],"version-history":[{"count":2,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/posts\/2090\/revisions"}],"predecessor-version":[{"id":2093,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/posts\/2090\/revisions\/2093"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/media\/1997"}],"wp:attachment":[{"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/media?parent=2090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/categories?post=2090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mainmind.com\/blog\/wp-json\/wp\/v2\/tags?post=2090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}