{"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>Du\u017ce jest na pocz\u0105tku ma\u0142e. Potem ro\u015bnie. Dotyczy to tak\u017ce oprogramowania. Zanim zrobi\u0119 \u201edu\u017c\u0105\u201d 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\u2019, 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>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>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>\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>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> 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>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<Friendship>? Friendships { get; set; }\n}\n\npublic class Friendship\n{\n    public int Id { get; set; }\n    public virtual ICollection<Person>? Persons { get; set; }\n}<\/code><\/pre><\/div>\n\n\n\n<p>Uzupe\u0142niamy <em>ApplicationContext<\/em> dodaj\u0105c poni\u017cej metody <em>OnConfiguring<\/em> obiekty <em>DbSet<> <\/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<Person>().HasData(new Person { Id = 1, Name = &quot;Ala&quot; });\n        modelBuilder.Entity<Person>().HasData(new Person { Id = 2, Name = &quot;Bolek&quot; });\n        modelBuilder.Entity<Person>().HasData(new Person { Id = 3, Name = &quot;Lolek&quot; });\n    }\n\n    public DbSet<Person> Persons { get; set; } = null!;\n    public DbSet<Friendship> Friendships { get; set; } = null!;<\/code><\/pre><\/div>\n\n\n\n<p>Nast\u0119pnie tworzymy pierwsz\u0105 migracj\u0119 oraz aplikujemy j\u0105 do bazy.<br><code>C:\\Users\\marek\\Alamakota> dotnet ef migrations add initial<br>C:\\Users\\marek\\Alamakota> 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>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>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>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>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 \u201edu\u017c\u0105\u201d 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\u2019, 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}]}}