@@ -302,7 +302,7 @@ d) Return a 404 status code if a course with the corresponding ID d
-
+
Handling HttpPatch Requests
The ID is fetched from the URI
@@ -323,7 +323,7 @@ d) Return a 404 status code if a course with the corresponding ID d
-
+
Exercise 4: Creating a PATCH Endpoint
Continue working on CourseAPI.
diff --git a/4-restful-http-methods.md b/4-restful-http-methods.md
index de2275a..2353b9e 100644
--- a/4-restful-http-methods.md
+++ b/4-restful-http-methods.md
@@ -24,8 +24,8 @@ title: 4. RESTful HTTP Methods
### RESTful API
* We'll be extending our Web API into a full-blown ***RESTful API***
- * More about REST in [Frontend Basics Lecture 3: REST Architecture](https://gitea.buutti.com/education/frontend-basics/src/branch/main/3-rest-architecture.md)
- * A good idea to also check out [Frontend Basics Lecture 2: HTTP methods](https://gitea.buutti.com/education/frontend-basics/src/branch/main/2-http.md)
+ * It's a good idea to check out [Webdev Basics: HTTP methods](https://gitea.buutti.com/education/webdev-basics/src/branch/main/http.md) first
+ * Also, some ramblings about REST in [Webdev Basics: REST Architecture](https://gitea.buutti.com/education/webdev-basics/src/branch/main/rest-architecture.md)
* We have so far implemented `GET` and `POST` methods for reading resources from the API and creating new ones to it, respectively
* All the primary methods for following the uniform interface requirement are `GET`, `POST`, `PUT`, `PATCH` and `DELETE`
* Others exist, but these are by far most commonly used
diff --git a/6-databases-with-entity-framework-slides.html b/6-databases-with-entity-framework-slides.html
index 02a2a14..5cb70ac 100644
--- a/6-databases-with-entity-framework-slides.html
+++ b/6-databases-with-entity-framework-slides.html
@@ -13,30 +13,36 @@
/* 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 gqy7k3kdx5d6t13nmmhm7jdgeg2yxye7r5enweiq2sgh */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%}
Use the Package Manager Console to "reverse engineer" the code for an existing database
@@ -503,7 +509,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.
@@ -514,13 +520,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 c07ddfc..67ccb11 100644
--- a/6-databases-with-entity-framework.md
+++ b/6-databases-with-entity-framework.md
@@ -16,11 +16,14 @@ 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
+ * Read [Webdev basics: SQL Databases](https://gitea.buutti.com/education/webdev-basics/src/branch/main/sql-databases.md) first!
* [Entity Framework](https://learn.microsoft.com/en-us/ef/) is an Object-Relational Mapper (ORM) made by Microsoft for the .NET framework
* Object-Relational Mapping: converting from database representation to objects in a programming language
* Allows creation of CRUD operations without writing SQL
diff --git a/README.md b/README.md
index 0101627..16ff1d3 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@
| 3 | [MVP Pattern and Repositories](3-mvc-pattern-and-repositories.md) | [Download slides](3-mvc-pattern-and-repositories-slides.html?raw=1) |
| 4 | [RESTful HTTP Methods](4-restful-http-methods.md) | [Download slides](4-restful-http-methods-slides.html?raw=1) |
| 5 | [Model Validation & API Design](5-model-validation-and-designing-apis.md) | [Download slides](5-model-validation-and-designing-apis-slides.html?raw=1) |
-| | [SQL Databases](sql-databases.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) |
diff --git a/imgs/7-databases-with-entity-framework_0.png b/imgs/7-databases-with-entity-framework_0.png
deleted file mode 100644
index 3fb3c4a..0000000
Binary files a/imgs/7-databases-with-entity-framework_0.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_1.png b/imgs/7-databases-with-entity-framework_1.png
deleted file mode 100644
index 4b397ea..0000000
Binary files a/imgs/7-databases-with-entity-framework_1.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_2.png b/imgs/7-databases-with-entity-framework_2.png
deleted file mode 100644
index 2c8f562..0000000
Binary files a/imgs/7-databases-with-entity-framework_2.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_3.png b/imgs/7-databases-with-entity-framework_3.png
deleted file mode 100644
index 9e7dee7..0000000
Binary files a/imgs/7-databases-with-entity-framework_3.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_4.png b/imgs/7-databases-with-entity-framework_4.png
deleted file mode 100644
index 03a1e2f..0000000
Binary files a/imgs/7-databases-with-entity-framework_4.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_5.png b/imgs/7-databases-with-entity-framework_5.png
deleted file mode 100644
index 2d57d7c..0000000
Binary files a/imgs/7-databases-with-entity-framework_5.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_6.png b/imgs/7-databases-with-entity-framework_6.png
deleted file mode 100644
index 23fd825..0000000
Binary files a/imgs/7-databases-with-entity-framework_6.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_7.png b/imgs/7-databases-with-entity-framework_7.png
deleted file mode 100644
index d0555d8..0000000
Binary files a/imgs/7-databases-with-entity-framework_7.png and /dev/null differ
diff --git a/imgs/7-databases-with-entity-framework_8.png b/imgs/7-databases-with-entity-framework_8.png
deleted file mode 100644
index 30401dc..0000000
Binary files a/imgs/7-databases-with-entity-framework_8.png and /dev/null differ
diff --git a/sql-databases-slides.html b/sql-databases-slides.html
deleted file mode 100644
index adfaefb..0000000
--- a/sql-databases-slides.html
+++ /dev/null
@@ -1,431 +0,0 @@
-SQL Databases
-
SQL Databases
-
-
-
What is SQL?
-
-
SQL, Structured Query Language is a language used to organize and manipulate data in a database
Inspect and edit data in pgAdmin by right-clicking a table and selecting View/Edit Data
-
-
-
-
-
-
-
-
-
-
-
-
Individual values in the table can be directly modified by double clicking the value and then editing the value in the visual user interface
-
Save the changes by pressing the Save Data Changes button
-
-
-
-
-
-
-
-
-
-
Exercise 1: Preparing the database
-
-
Using either PgAdmin or PSQL,
-
-
Create a new database called sqlpractice
-
Insert the provided example query to the new database
-
Verify that the query has created new tables to your database
-
-
-
-
Basic SQL queries
-
-
SELECT
-
INSERT
-
DELETE
-
UPDATE
-
CREATE & DROP
-
-
-
-
Querying data with SELECT
-
-
Syntax:
SELECT column1, column2, column3 FROM table_name;
-
-
-
Examples:
SELECT full_name, email FROM users;
-SELECT full_name AS name, email FROM users;
-SELECT*FROM users;
-
-
-
-
-
-
Filtering data with WHERE
-
-
Syntax:
SELECT column1, column2 FROM table_name WHEREcondition;
-
-
-
-
-
-
-
Text is captured in single quotes.
-
LIKE condition uses the % sign as a wildcard.
-
IS and IS NOT are also valid operators.
-
-
-
-
-
Example:
SELECT full_name FROM users
-WHERE full_name ='Teppo Testaaja';
-
-SELECT*FROM books WHERE name LIKE'%rr%';
-SELECT*FROM books WHERE author ISNOTnull;
-
-
-
-
-
-
-
-
Ordering data with ORDER BY
-
-
Syntax:
SELECT column1 FROM table_name ORDERBY column1 ASC;
-
-
-
Examples:
SELECT full_name FROM users
-ORDERBY full_name ASC;
-
-SELECT full_name FROM users
-ORDERBY full_name DESC;
-
Object-Relational Mappers, or ORMs allow the developer to write code instead of SQL to perform CRUD operations on their database
-
An abstraction layer between code and database
-
-
Can make database logic easier to read and write
-
Prevents SQL injection by sanitizing input (see the comic before...)
-
...but sometimes you'd rather just write the SQL queries themselves
-
-
-
Some popular ORMs:
-
-
Hibernate (Java)
-
EFCore (.NET)
-
Sequelize (Node.js)
-
TypeORM (TypeScript)
-
-
-
-
-
\ No newline at end of file
diff --git a/sql-databases.md b/sql-databases.md
deleted file mode 100644
index 6bedbd8..0000000
--- a/sql-databases.md
+++ /dev/null
@@ -1,400 +0,0 @@
----
-marp: true
-paginate: true
-math: mathjax
-theme: buutti
-title: SQL Databases
----
-
-# SQL Databases
-
-
-
-
-## What is SQL?
-
-* SQL, Structured Query Language is a language used to organize and manipulate data in a database
-* Originally developed by IBM in the 70's
- * Quickly became the most popular database language
- ```sql
- SELECT id, email
- FROM users
- WHERE first_name = 'Teppo';
- ```
-
-## Relational Database Management Systems
-
-* In relational databases, values are stored in *__tables__*
- * Each table has *__rows__* and *__columns__*
- * Data is displayed in a two-dimensional matrix
-* Values in a table are related to each other
- * Values can also be related to values in other tables
-* A relational database management system (RDBMS) is a program that executes queries to relational databases
-
----
-
-
-
-[https://db-engines.com/en/ranking](https://db-engines.com/en/ranking)
-
-## PostgreSQL
-
-* Free and open-source, cross-platform relational database management system
-* Emphasizes extensibility and SQL compliance
-* Fully ACID-compliant (atomicity, consistency, isolation and durability)
-* Used in conjunction with ***pgAdmin***
- * Administration and development platform for PostgreSQL
- * Cross-platform, features a web interface
- * Basically a control panel application for your PostgreSQL database
-
-### PostgreSQL: Creating a Database
-
-
-
-
-With pgAdmin:
-1) Right-click *Servers > my-postgres > Databases*
-2) Select _Create > Database..._
-3) Insert a name for the database and hit _Save_
-
-
-
----
-
-With psql:
-
-1) List all available databases with `\l`
-2) Connect to the created database with `\c `
-3) List all tables in the database with `\dt`
-4) Type a query and press enter
- * Here's an [example query](code-examples/example-query.sql)
-
-## Editing Data with pgAdmin
-
-
-
-
-* Inspect and edit data in pgAdmin by right-clicking a table and selecting _View/Edit Data_
-
-
-
-* Individual values in the table can be directly modified by double clicking the value and then editing the value in the visual user interface
-* Save the changes by pressing the _Save Data Changes_ button
-
-
-
-## Exercise 1: Preparing the database
-
-
-Using either PgAdmin or PSQL,
-
-1) Create a new database called `sqlpractice`
-2) Insert the provided [example query](code-examples/example-query.sql) to the new database
-3) Verify that the query has created new tables to your database
-
-## Basic SQL queries
-
-* `SELECT`
-* `INSERT`
-* `DELETE`
-* `UPDATE`
-* `CREATE` & `DROP`
-
-### Querying data with `SELECT`
-
-* Syntax:
- ```sql
- SELECT column1, column2, column3 FROM table_name;
- ```
-* Examples:
- ```sql
- SELECT full_name, email FROM users;
- SELECT full_name AS name, email FROM users;
- SELECT * FROM users;
- ```
-
-### Filtering data with `WHERE`
-
-* Syntax:
- ```sql
- SELECT column1, column2 FROM table_name WHERE condition;
- ```
-
-
-
-* Text is captured in **_single quotes_**.
-* `LIKE` condition uses the `%` sign as a wildcard.
-* `IS` and `IS NOT` are also valid operators.
-
-
-
-
-* Example:
- ```sql
- SELECT full_name FROM users
- WHERE full_name = 'Teppo Testaaja';
-
- SELECT * FROM books WHERE name LIKE '%rr%';
- SELECT * FROM books WHERE author IS NOT null;
- ```
-
-
-
-
-### Ordering data with `ORDER BY`
-
-* Syntax:
- ```sql
- SELECT column1 FROM table_name ORDER BY column1 ASC;
- ```
-* Examples:
- ```sql
- SELECT full_name FROM users
- ORDER BY full_name ASC;
-
- SELECT full_name FROM users
- ORDER BY full_name DESC;
- ```
-
-### Combining data with `JOIN`
-
-* Also known as `INNER JOIN`
-* Corresponds to ***intersection*** from [set theory](https://en.wikipedia.org/wiki/Set_theory)
-
-
-
-#### JOIN examples
-
-```sql
-SELECT
-users.id, users.full_name, borrows.id,
-borrows.user_id, borrows.due_date, borrows.returned_at
-FROM users
-JOIN borrows ON
-users.id = borrows.user_id;
-```
-
-```sql
-SELECT
-U.full_name AS name,
-B.due_date AS due_date,
-B.returned_at AS returned_at
-FROM users AS U
-JOIN borrows AS B ON
-U.id = B.user_id;
-```
-
-### Combining with `LEFT JOIN`
-
-
-
-
-* Also known as `LEFT OUTER JOIN`
-* Example:
- ```sql
- SELECT
- U.full_name AS name,
- B.due_date AS due_date,
- B.returned_at AS returned_at
- FROM users AS U
- LEFT JOIN borrows AS B ON
- U.id = B.user_id;
- ```
-
-
-
-### Exercise 2: Querying the library
-
-
-Using SQL queries, get
-
-1) all columns of `borrows` that are borrowed before `2020-10-27`
-2) all columns of `borrows` that are returned
-3) columns `user.full_name` and `borrows.borrowed_at` of the user with an `id` of 1
-4) columns `book.name`, `book.release_year` and `language.name` of all books that are released after 1960
-
-### Inserting data with `INSERT`
-
-* Syntax
- ```sql
- INSERT INTO table_name (column1, column2, column3) VALUES (value1, value2, value3);
- ```
-* Example
- ```sql
- INSERT INTO users (full_name, email, created_at)
- VALUES ('Pekka Poistuja', 'pekka.poistuja@buutti.com', NOW());
- ```
-* Since id is not provided, it will be automatically generated.
-
-### Updating data with `UPDATE`
-
-* Syntax
- ```sql
- UPDATE table_name SET column1 = value1, column2 = value2 WHERE condition;
- ```
-* *__Notice:__* if a condition is not provided, all rows will be updated!
- * If updating only one row, it is usually best to use `id`.
-* Example
- ```sql
- UPDATE users SET email = 'taija.testaaja@gmail.com' WHERE id = 2;
- ```
-
-## Removing data with `REMOVE`
-
-* Syntax
- ```sql
- DELETE FROM table_name WHERE condition;
- ```
-* Again, if the _condition_ is not provided, `DELETE` affects _all_ rows
-* Before deleting, it is a good practice to execute an equivalent `SELECT` query to make sure that only the proper rows will be affected.
-* Example:
- ```sql
- SELECT * FROM users WHERE id = 5;
- DELETE FROM users WHERE id = 5;
- ```
-
-### Exercise 3: Editing data
-
-
-1) Postpone the due date of the borrow with an `id` of `1` by two days in the `borrows` table
-2) Add a couple of new books to the `books` table
-3) Delete one of the borrows.
-
-### Initializing data with `CREATE TABLE`
-
-* Before data can be manipulated, a database and its tables need to be initialized.
-
-
-
-* Example:
- ```sql
- CREATE TABLE "users" (
- "id" SERIAL PRIMARY KEY,
- "full_name" varchar NOT NULL,
- "email" varchar UNIQUE NOT NULL,
- "created_at" timestamp NOT NULL
- );
- ```
-
-
-
-
-### Removing data with `DROP`
-
-* In order to remove tables or databases, we use a `DROP` statement
- ```sql
- DROP TABLE table_name;
- DROP DATABASE database_name;
- ```
-* These statements do not ask for confirmation and there is no undo feature. Take care when using a drop statement.
-
----
-
-* I'm legally obliged to include this XKCD comic here.
-
-
-
-## NoSQL
-
-* In addition to SQL databases, there's ***NoSQL***
-* There are many differing definitions, but...
- * most agree that NoSQL databases store data in a format other than tables
- * They can still store relational data - just _differently_
-* Four different database types:
- * Document databases
- * Key-value databases
- * Wide-column stores
- * Graph databases
-* Example database engines include [MongoDB](https://www.mongodb.com/), [Redis](https://redis.io/) and [Cassandra](https://cassandra.apache.org/_/index.html)
-* For more info, see [MongoDB: What is NoSQL?](https://www.mongodb.com/resources/basics/databases/nosql-explained)
-
-
-## Object-Relational Mappers
-
-* Object-Relational Mappers, or ORMs allow the developer to write code instead of SQL to perform CRUD operations on their database
-* An abstraction layer between code and database
- * Can make database logic easier to read and write
- * Prevents SQL injection by sanitizing input (see the comic before...)
- * ...but sometimes you'd rather just write the SQL queries themselves
-* Some popular ORMs:
- * Hibernate (Java)
- * EFCore (.NET)
- * Sequelize (Node.js)
- * TypeORM (TypeScript)