diff --git a/6-databases-with-entity-framework-slides.html b/6-databases-with-entity-framework-slides.html index 5cb70ac..7a2c61f 100644 --- a/6-databases-with-entity-framework-slides.html +++ b/6-databases-with-entity-framework-slides.html @@ -13,20 +13,19 @@ /* buutti.css */ /* @theme buutti */div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns12{display:grid;grid-template-columns:1fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns21{display:grid;grid-template-columns:2fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns32{display:grid;grid-template-columns:3fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns23{display:grid;grid-template-columns:2fr 3fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns111{display:grid;grid-template-columns:1fr 1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .centered{display:flex;flex-direction:column;justify-content:center;text-align:center}div#\:\$p>svg>foreignObject>section .tableborderless td,div#\:\$p>svg>foreignObject>section th{border:none!important;border-collapse:collapse}div#\:\$p>svg>foreignObject>section.extra{background-color:#5d275d;background-image:linear-gradient(to bottom,#401a40,#1d0c1d);color:white}div#\:\$p>svg>foreignObject>section.extra a{color:rgb(145,255,209)}div#\:\$p>svg>foreignObject>section.exercise{background-color:#29366f;background-image:linear-gradient(to bottom,#20636a,#173742);color:white}div#\:\$p>svg>foreignObject>section.exercise a{color:rgb(211,173,255)} -/* @theme qxwzalhzytjx5wnlf6losqvbl44tf0bt7if1oe7ch9 */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}
+/* @theme ood9p0kg55vt1iq8tsdr2xnz4hx4dv18g1kl5unxk8 */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}

Databases with Entity Framework

-
+

Contents

-
+

Entity Framework (EF)

  • This lecture will assume you have a basic understanding of SQL databases @@ -42,7 +41,7 @@
  • Allows creation of CRUD operations without writing SQL
-
+

Entity Framework Core (EF Core)

  • EF Core is a cross-platform version of EF
  • @@ -52,7 +51,7 @@
  • This is what we'll be using
-
+

Code First vs Database First vs Model First

  • There are three approaches through which Entity Framework can be implemented @@ -65,7 +64,7 @@
  • Database First and Code First are the most used ones and will be introduced in this lecture
-
+

Note about loading data

  • In EF Core, you can use navigation properties in your model to load related entities
  • @@ -78,10 +77,10 @@
-
+

Code First approach

-
+

Code First

  • In the Code First approach, Entity Framework will create databases and tables based on defined entity classes
  • @@ -101,7 +100,7 @@
  • Not preferred for data intensive applications
-
+

Required Packages

  • Install and add the following packages to your project: @@ -116,7 +115,7 @@

-
+

Code First: DbContext

  • Let's begin with the Code First Approach
  • @@ -131,7 +130,7 @@ b) classes to keep the database up-to-date with CRUD operations
-
+

Creating a context

  • Create a context that inherits from DbContext @@ -151,7 +150,7 @@ b) classes to keep the database up-to-date with CRUD operations
-
+
  • To further configure how the database will be structured, override the OnModelCreating method
  • In this example, one table named Contact with columns Id, Name and Email will be created:
    public class ContactsContext : DbContext
    @@ -168,7 +167,7 @@ b) classes to keep the database up-to-date with CRUD operations
     
-
+
  • In this example, the Contact table will be created with some starting values for Id, Name and Email columns:
    public class ContactsContext : DbContext
     {
    @@ -187,7 +186,7 @@ b) classes to keep the database up-to-date with CRUD operations
     
-
+

DbContext as a Service

  • In Program.cs, add the context to services with AddDbContext method
  • @@ -204,7 +203,7 @@ services.AddControllers().AddNewtonsoftJson();
-
+

Migrations

  • As the development progresses, models and database schemas change over time @@ -220,7 +219,7 @@ services.AddControllers().AddNewtonsoftJson();
  • EFCore migrations have built-in version control; a snapshot of each version of the schema is stored
-
+

Applying migrations

  • Open the Package Manager Console in Visual Studio @@ -241,7 +240,7 @@ services.AddControllers().AddNewtonsoftJson();
-
+
  • At this point, the values you have entered (Contacts table in this example) should show up in the database. You can check it up e.g. in pgAdmin.
@@ -262,7 +261,7 @@ services.AddControllers().AddNewtonsoftJson();
-
+

Exercise 1: Adding Context

Continue working on the CourseAPI.

@@ -275,7 +274,7 @@ services.AddControllers().AddNewtonsoftJson();
  • Check that the Course table with the starting values has appeared to the database
  • -
    +

    Using DbContext in the API

    • Because DbContext is added to services, it can be accessed from any other service, such as the repository
    • @@ -289,7 +288,7 @@ services.AddControllers().AddNewtonsoftJson();
    • After modifying the DbSet, update the changes to the database with the DbContext.SaveChanges() method
    -
    +

    Injecting DbContext

    • Inject the DbContext to your repositories as you would any other service:
      public class ContactRepository : IContactRepository
      @@ -306,7 +305,7 @@ services.AddControllers().AddNewtonsoftJson();
       
    -
    +

    DbContext: Read Operations

    public class ContactRepository : IContactRepository
     {
    @@ -321,7 +320,7 @@ services.AddControllers().AddNewtonsoftJson();
     }
     
    -
    +

    DbContext: Create Operations

    public class ContactRepository : IContactRepository
     {
    @@ -339,7 +338,7 @@ services.AddControllers().AddNewtonsoftJson();
     }
     
    -
    +

    DbContext: Update Operations

    public class ContactRepository : IContactRepository
     {
    @@ -360,7 +359,7 @@ services.AddControllers().AddNewtonsoftJson();
     }
     
    -
    +

    DbContext: Delete Operations

    public class ContactRepository : IContactRepository
     {
    @@ -378,7 +377,7 @@ services.AddControllers().AddNewtonsoftJson();
     }
     
    -
    +

    Exercise 2: CRUD on the DB

    Continue working on CourseAPI.

    @@ -387,7 +386,7 @@ services.AddControllers().AddNewtonsoftJson();
  • Test with Postman. Keep refreshing the DB in pgAdmin or creating queries with psql to make sure the requests work as intended
  • -
    +

    Summing Things Up

    • Now the API has been hooked up to a PostgreSQL database
    • @@ -396,7 +395,7 @@ services.AddControllers().AddNewtonsoftJson();
    • Controllers accepting HTTP requests have access to the repository
    -
    +

    EFCore Code First Checklist

    1. Install required packages
    2. @@ -406,7 +405,7 @@ services.AddControllers().AddNewtonsoftJson();
    3. Add CRUD operations to the database repository
    -
    +

    Modifying the Relations

    • Let's change the structure of our Contacts API by adding a new class Account @@ -418,7 +417,7 @@ services.AddControllers().AddNewtonsoftJson();
    • Emails will be removed from the Contacts table
    -
    +
    // Models/Contact.cs
     public class Contact
     {
    @@ -438,13 +437,13 @@ services.AddControllers().AddNewtonsoftJson();
     }
     
    -
    +
    • Adding a migration at this point will result in a warning:
    -
    +
      @@ -466,7 +465,7 @@ services.AddControllers().AddNewtonsoftJson();
    -
    +

    Exercise 3: Adding Migrations

    Continue working on CourseAPI.

    @@ -477,10 +476,10 @@ services.AddControllers().AddNewtonsoftJson();
  • Update the database. Check that the changes show up in the database with pgAdmin
  • -
    +

    Database First approach

    -
    +

    What is the Database First approach?

    • This is the other approach for creating a connection between the database and the application
    • @@ -495,7 +494,7 @@ services.AddControllers().AddNewtonsoftJson();
    -
    +

    Scaffolding

    • Use the Package Manager Console to "reverse engineer" the code for an existing database @@ -509,7 +508,7 @@ services.AddControllers().AddNewtonsoftJson();
    • Using the connection string corresponding to your database, this will create all the classes for the entities in the DB as well as the context class
    -
    +

    Exercise 4: Database First

    Create a new ASP.NET Core web app using the API template.

    @@ -520,13 +519,13 @@ b) by copying the <PackageReference> lines from the .cs
  • Scaffold the sqlpractice database created in SQL Databases Exercise 1 to the project by using the Database First approach. If you have not yet created the database in PostgreSQL, it can be found here
  • -
    +

    Reading: Authentication with roles

    • Here's an example how to do a role-based authentication by using JWT tokens
    -
    +

    Exercise 5 (Extra): Connection

    Continuing the previous exercise,

    diff --git a/6-databases-with-entity-framework.md b/6-databases-with-entity-framework.md index 67ccb11..c121ee7 100644 --- a/6-databases-with-entity-framework.md +++ b/6-databases-with-entity-framework.md @@ -16,10 +16,8 @@ title: 5. Databases with Entity Framework - [Entity Framework (EF)](#entity-framework-ef) - [Code First approach](#code-first-approach) - [Migrations](#migrations) -- [Migrations](#migrations) - [Database First approach](#database-first-approach) - ## Entity Framework (EF) * This lecture will assume you have a basic understanding of SQL databases diff --git a/README.md b/README.md index 16ff1d3..5c6d182 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,4 @@ | 5 | [Model Validation & API Design](5-model-validation-and-designing-apis.md) | [Download slides](5-model-validation-and-designing-apis-slides.html?raw=1) | | 6 | [Databases with Entity Framework](6-databases-with-entity-framework.md) | [Download slides](6-databases-with-entity-framework-slides.html?raw=1) | | 7 | [Authentication and Authorization](7-authentication-and-authorization.md) | [Download slides](7-authentication-and-authorization-slides.html?raw=1) | -| 8 | [Testing](8-testing.md) | [Download slides](8-testing-slides.html?raw=1) | +| 8 | [Testing](8-testing.md) | [Download slides](8-testing-slides.html?raw=1) | \ No newline at end of file