{"id":704,"date":"2023-02-19T16:06:50","date_gmt":"2023-02-19T15:06:50","guid":{"rendered":"https:\/\/blog.adameczek.pl\/?p=704"},"modified":"2024-06-26T13:15:11","modified_gmt":"2024-06-26T11:15:11","slug":"prototypowanie-bazy-danych-z-entity-framework","status":"publish","type":"post","link":"https:\/\/blog.adameczek.pl\/index.php\/2023\/02\/19\/prototypowanie-bazy-danych-z-entity-framework\/","title":{"rendered":"Prototypowanie bazy danych z Entity Framework"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Du\u017ce jest na pocz\u0105tku ma\u0142e. Potem ro\u015bnie. Dotyczy to tak\u017ce oprogramowania. Zanim zrobi\u0119 &#8222;du\u017c\u0105&#8221; baz\u0119, to czasem mam potrzeb\u0119 wykonania prototypu. Nie musi on odzwierciedla\u0107 wszystkich encji, ale te kt\u00f3rych powi\u0105zania chc\u0119 sprawdzi\u0107. Po co tak? W przypadku Entity Framework, warto popatrze\u0107, co wyprodukuje framework czy to z modeli i 'annotations&#8217;, czy z kodu fluent api. To nie jest to T-SQL, gdzie widz\u0119, co pisz\u0119 \ud83d\ude09 Dlatego szybki prototyp si\u0119 przydaje. W tym celu robi\u0119 sobie migracj\u0119 i aplikuj\u0119 j\u0105 do bazy. Wtedy wida\u0107 jaka b\u0119dzie finalna posta\u0107 moich zamierze\u0144. Mog\u0119 j\u0105 te\u017c przetestowa\u0107.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nie przed\u0142u\u017caj\u0105c, bo to ma by\u0107 szybki prototyp a pizza ju\u017c jest w piekarniku, zabieramy si\u0119 do pracy \ud83d\ude09<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Robimy sobie folder na nasz\u0105 aplikacj\u0119, w kt\u00f3rej utworzymy modele encji. Zak\u0142adam, \u017ce .NET SDK i MSSQL Server mamy zainstalowane. Potrzebne te\u017c b\u0119dzie narz\u0119dzie <code>dotnet-ef<\/code>. Kto ma, to pomija pierwsze polecenie.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>dotnet tool install --global dotnet-ef\nmd Alamakota\ncd Alamakota\ndonet new console\ndotnet add package Microsoft.EntityFrameworkCore\ndotnet add package Microsoft.EntityFrameworkCore.SqlServer\ndotnet add package Microsoft.EntityFrameworkCore.Design<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">\u015arodowisko testowe mamy gotowe. Teraz przyszed\u0142 czas na obiekt, kt\u00f3ry b\u0119dzie testowany. Otwieramy projekt w ulubionym IDE i dodajemy DbContext.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism off-numbers lang-csharp\" data-file=\"Alamakota.cs\" data-lang=\"C#\"><code>using Alamakota.Entities;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Alamakota;\n\npublic class ApplicationContext : DbContext\n{\n    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n    {\n        optionsBuilder.UseSqlServer(@&quot;Data Source=.\\SQLEXPRESS;Initial Catalog=ala-test;Integrated Security=True;Trust Server Certificate=Yes&quot;);\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">To sprawd\u017amy, czy wszystko jest w porz\u0105dku? Poni\u017csza komenda powinna zbudowa\u0107 aplikacj\u0119 i zwr\u00f3ci\u0107 wynik:<br><code>C:\\Users\\marek\\Alamakota&gt; dotnet ef migrations list<\/code> <br><code>Build started\u2026<br>Build succeeded.<br>No migrations were found.<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fakt, nie mamy jeszcze migracji, ani bazy, ale wiemy, \u017ce aplikacja si\u0119 buduje i mamy po\u0142\u0105czenie z serwerem. To czas na jakie\u015b modele, np.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism off-numbers lang-csharp\" data-file=\"Entities.cs\" data-lang=\"C#\"><code>namespace Alamakota.Entities;\n\npublic class Person\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = null!;\n\n    public virtual ICollection&lt;Friendship&gt;? Friendships { get; set; }\n}\n\npublic class Friendship\n{\n    public int Id { get; set; }\n    public virtual ICollection&lt;Person&gt;? Persons { get; set; }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Uzupe\u0142niamy <em>ApplicationContext<\/em> dodaj\u0105c poni\u017cej metody <em>OnConfiguring<\/em> obiekty <em>DbSet&lt;&gt; <\/em>i inicjalizujemy baz\u0119 danymi. <\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism off-numbers lang-csharp\" data-file=\"ApplicationContext.cs\" data-lang=\"C#\"><code>    protected override void OnModelCreating(ModelBuilder modelBuilder)\n    {\n        modelBuilder.Entity&lt;Person&gt;().HasData(new Person { Id = 1, Name = &quot;Ala&quot; });\n        modelBuilder.Entity&lt;Person&gt;().HasData(new Person { Id = 2, Name = &quot;Bolek&quot; });\n        modelBuilder.Entity&lt;Person&gt;().HasData(new Person { Id = 3, Name = &quot;Lolek&quot; });\n    }\n\n    public DbSet&lt;Person&gt; Persons { get; set; } = null!;\n    public DbSet&lt;Friendship&gt; Friendships { get; set; } = null!;<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Nast\u0119pnie tworzymy pierwsz\u0105 migracj\u0119 oraz aplikujemy j\u0105 do bazy.<br><code>C:\\Users\\marek\\Alamakota&gt; dotnet ef migrations add initial<br>C:\\Users\\marek\\Alamakota&gt; dotnet ef database update<\/code><br>Serwer powinien pokaza\u0107 now\u0105 baz\u0119 i tabele.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" width=\"227\" height=\"199\" src=\"https:\/\/blog.adameczek.pl\/wp-content\/uploads\/2023\/02\/image.png\" alt=\"\" class=\"wp-image-707\"\/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">I to by by\u0142o w zasadzie wszystko, co istotne. Mamy baz\u0119, kt\u00f3rej struktur\u0119 chcieli\u015bmy sprawdzi\u0107. Dla mnie najwa\u017cniejszy jest plik <em>ApplicationContextModelSnapshot.cs<\/em> kt\u00f3ry Entity Framework utworzy\u0142 w folderze <em>Migrations<\/em>. W nim widz\u0119, jak framework prze\u0142o\u017cy\u0142 m\u00f3j kod na polecenia fluent api, kt\u00f3re s\u0105 odzwierciedlane w bazie danych. Trzeba jednak pami\u0119ta\u0107, \u017ce ten kod, nie pokazuje w 100% tego co si\u0119 wydarzy w bazie. Framework pos\u0142uguje si\u0119 pewnymi ustawieniami domy\u015blnymi. W kodzie fluent api nie wszystko jest uwidocznione. Np. domy\u015blnie na kluczu g\u0142\u00f3wnym zak\u0142adany jest indeks klastrowy, a w kodzie tego nie wida\u0107. Zawsze jednak mo\u017cna sobie z poziomu MSSMS wygenerowa\u0107 skrypt odtwarzaj\u0105cy interesuj\u0105cy element, np. tabel\u0119. Tam ju\u017c nic nam nie umknie \ud83d\ude42<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Na zako\u0144czenie wisienka na torcie. Sprawd\u017amy, \u017ce nasz <em>DbContext<\/em> si\u0119gnie dane z bazy. Zamieniamy zawarto\u015b\u0107<em> Program.cs <\/em>na nast\u0119puj\u0105c\u0105:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism off-numbers lang-csharp\" data-file=\"Program.cs\" data-lang=\"C#\"><code>using Alamakota;\n\nusing var dbContext = new ApplicationContext();\nvar persons = dbContext.Persons;\n\nforeach (var person in persons)\n{\n    Console.WriteLine(person.Name);\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">I po wydaniu komendy<code> dotnet run<\/code> powinni\u015bmy zobaczy\u0107:<br><code>Ala<\/code><br><code>Bolek<\/code><br><code>Lolek<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pizza gotowa. To ju\u017c wszystko na dzi\u015b \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Du\u017ce jest na pocz\u0105tku ma\u0142e. Potem ro\u015bnie. Dotyczy to tak\u017ce oprogramowania. Zanim zrobi\u0119 &#8222;du\u017c\u0105&#8221; baz\u0119, to czasem mam potrzeb\u0119 wykonania prototypu. Nie musi on odzwierciedla\u0107 wszystkich encji, ale te kt\u00f3rych powi\u0105zania chc\u0119 sprawdzi\u0107. Po co tak? W przypadku Entity Framework, warto popatrze\u0107, co wyprodukuje framework czy to z modeli i 'annotations&#8217;, czy z kodu fluent [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1003,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"0","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"0","ocean_custom_header_template":"0","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0","_jetpack_memberships_contains_paid_content":false,"ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"off","ocean_gallery_id":[],"footnotes":""},"categories":[10],"tags":[20,18],"class_list":["post-704","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","tag-entityframework","tag-net","entry","has-media"],"jetpack_featured_media_url":"https:\/\/blog.adameczek.pl\/wp-content\/uploads\/2023\/02\/EFCore-thumb.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts\/704","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/comments?post=704"}],"version-history":[{"count":7,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts\/704\/revisions"}],"predecessor-version":[{"id":729,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/posts\/704\/revisions\/729"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/media\/1003"}],"wp:attachment":[{"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/media?parent=704"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/categories?post=704"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.adameczek.pl\/index.php\/wp-json\/wp\/v2\/tags?post=704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}