Skip to content

Commit 490935b

Browse files
authored
Session12 (#55)
* Initialized session 12 samples * Completed sample EF context interactions * Added notes and migrations to show relations in database * updated with final state after broadcast
1 parent 3015704 commit 490935b

20 files changed

+998
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dotnet-test-explorer.testProjectPath": "**/*Test.@(csproj|vbproj|fsproj)",
3+
"dotnet-test-explorer.autoWatch": true,
4+
"dotnet-test-explorer.showCodeLens": true
5+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
// Use IntelliSense to find out which attributes exist for C# debugging
3+
// Use hover for the description of the existing attributes
4+
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": ".NET Core Launch (console)",
9+
"type": "coreclr",
10+
"request": "launch",
11+
"preLaunchTask": "build",
12+
// If you have changed target frameworks, make sure to update the program path.
13+
"program": "${workspaceFolder}/SampleEntityFramework/bin/Debug/net5.0/SampleEntityFramework.dll",
14+
"args": [],
15+
"cwd": "${workspaceFolder}/SampleEntityFramework",
16+
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
17+
"console": "internalConsole",
18+
"stopAtEntry": false
19+
},
20+
{
21+
"name": ".NET Core Attach",
22+
"type": "coreclr",
23+
"request": "attach",
24+
"processId": "${command:pickProcess}"
25+
}
26+
]
27+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "build",
6+
"command": "dotnet",
7+
"type": "process",
8+
"args": [
9+
"build",
10+
"${workspaceFolder}/SampleEntityFramework/SampleEntityFramework.csproj",
11+
"/property:GenerateFullPaths=true",
12+
"/consoleloggerparameters:NoSummary"
13+
],
14+
"problemMatcher": "$msCompile"
15+
},
16+
{
17+
"label": "publish",
18+
"command": "dotnet",
19+
"type": "process",
20+
"args": [
21+
"publish",
22+
"${workspaceFolder}/SampleEntityFramework/SampleEntityFramework.csproj",
23+
"/property:GenerateFullPaths=true",
24+
"/consoleloggerparameters:NoSummary"
25+
],
26+
"problemMatcher": "$msCompile"
27+
},
28+
{
29+
"label": "watch",
30+
"command": "dotnet",
31+
"type": "process",
32+
"args": [
33+
"watch",
34+
"run",
35+
"${workspaceFolder}/SampleEntityFramework/SampleEntityFramework.csproj",
36+
"/property:GenerateFullPaths=true",
37+
"/consoleloggerparameters:NoSummary"
38+
],
39+
"problemMatcher": "$msCompile"
40+
}
41+
]
42+
}

sessions/0112-EfCore/0112-EfCore.sln

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.26124.0
5+
MinimumVisualStudioVersion = 15.0.26124.0
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleEntityFramework", "SampleEntityFramework\SampleEntityFramework.csproj", "{912529D4-72BB-41C7-96BA-B4B8DE8740EC}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Debug|x64 = Debug|x64
12+
Debug|x86 = Debug|x86
13+
Release|Any CPU = Release|Any CPU
14+
Release|x64 = Release|x64
15+
Release|x86 = Release|x86
16+
EndGlobalSection
17+
GlobalSection(SolutionProperties) = preSolution
18+
HideSolutionNode = FALSE
19+
EndGlobalSection
20+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
21+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
23+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Debug|x64.ActiveCfg = Debug|Any CPU
24+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Debug|x64.Build.0 = Debug|Any CPU
25+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Debug|x86.ActiveCfg = Debug|Any CPU
26+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Debug|x86.Build.0 = Debug|Any CPU
27+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Release|Any CPU.Build.0 = Release|Any CPU
29+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Release|x64.ActiveCfg = Release|Any CPU
30+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Release|x64.Build.0 = Release|Any CPU
31+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Release|x86.ActiveCfg = Release|Any CPU
32+
{912529D4-72BB-41C7-96BA-B4B8DE8740EC}.Release|x86.Build.0 = Release|Any CPU
33+
EndGlobalSection
34+
EndGlobal

sessions/0112-EfCore/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Session 12 - Entity Framework Core and Data
2+
3+
We've worked with all sorts of in-memory data storage, manipulation and retrieval up to this point. Let's start working with a database and write some content to disk. In .NET, we use Entity Framework Core to interact with relational databases. While this isn't the only way that you can interact with a database, its the preferred way by many because of the ease of use of Entity Framework Core as an object-relational mapper to convert our object interactions into actions to take against database records.
4+
5+
## The Setup
6+
7+
Let's create a console application as a test-bed for interacting with a database. Additionally, to ensure that these samples work on every platform and require no additional setup, we will use SQLite (a file-based database) to persist our data.
8+
9+
We can add EntityFramework Core to our project with these commands:
10+
11+
```
12+
dotnet add package Microsoft.EntityFrameworkCore
13+
dotnet add package Microsoft.EntityFrameworkCore.Tools
14+
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
15+
```
16+
17+
This will fetch the NuGet package containing the libraries and all of the tools for working with our database and add them to our project.
18+
19+
20+
## Introducing DbContext
21+
22+
DbContext is your gateway to the database. A descendent of this class contains table references and configuration to connect to your database. There are two ways to work with this class:
23+
24+
- Create the class and its classes to work with FIRST, called "Code First"
25+
- Extract a definition and class hierarchy from your existing database, called "Data First"
26+
27+
### Defining a class to be stored in a table
28+
29+
We'll focus on a Code First approach to working with the database. In this sample, we'll manage a database for our blog. Let's create a simple Blogpost type:
30+
31+
```c#
32+
public class BlogPost {
33+
34+
public int Id { get; set; }
35+
36+
public string Title { get; set; }
37+
38+
public DateTime PublishedUtc { get; set; }
39+
40+
public string Content { get; set; }
41+
42+
public override string ToString() {
43+
return $"{Title} ({Id})";
44+
}
45+
46+
}
47+
```
48+
49+
We can create a `DbContext` for our blog and add a property of type `DbSet<BlogPost>` to define a table to be created for our `BlogPost` objects:
50+
51+
```c#
52+
public class AppDbContext : DbContext
53+
{
54+
55+
public DbSet<BlogPost> Posts { get; set; }
56+
57+
}
58+
```
59+
60+
When we want to interact with the `BlogPost` objects in the database, we'll reach into the `Posts` property and use standard LINQ queries as well as collection interactions to add, update, and delete records from the database.
61+
62+
## EF Tools
63+
64+
With these C# classes created, how do we complete the connection to the database? Enter the ef tools. These are global tools that run at the command-line and allow you to manage the connection and definition of the database your code will work with.
65+
66+
### Installation
67+
68+
You can intsall the latest version of the ef tools using the following command:
69+
70+
```
71+
dotnet tool install --global dotnet-ef
72+
```
73+
74+
When a new version is available, you can update with this command:
75+
76+
```
77+
dotnet tool update dotnet-ef --global
78+
```
79+
80+
You will now be able to use `ef` tools from the dotnet command line to interact with the database. First, we'll want to configure a connection to the database. In this sample, we'll add a method to our `AppDbContext` class, but in real-world applications this would be fetched from application configuration and passed in:
81+
82+
```c#
83+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
84+
{
85+
86+
var conn = @"Data Source=appdb.db;";
87+
optionsBuilder.UseSqlite(conn);
88+
89+
base.OnConfiguring(optionsBuilder);
90+
}
91+
```
92+
93+
### Migrations
94+
95+
We can now start creating **Migrations**, blocks of code that maintain the schema of the database. Each migration is a unit that can be applied and removed programmatically from the database. Create your first migration to define the `BlogPost` storage using this command:
96+
97+
```
98+
dotnet ef migrations add "Add BlogPosts"
99+
```
100+
101+
This will create the `Migrations` folder and add some files to it with the definitions of the `Posts` table. Each time we modify the objects that will be stored in the database, we need to create additional migrations to be applied to the database.
102+
103+
### Database Update
104+
105+
We can apply any newly created migrations to our database with this command:
106+
107+
```
108+
dotnet ef database update
109+
```
110+
111+
You can also go the _OTHER WAY_ and create your DbContext and objects from the database using the command:
112+
113+
```
114+
dotnet ef dbcontext scaffold "Data Source=appdb.db" Microsoft.EntityFrameworkCore.Sqlite
115+
```
116+
117+
## CRUD Operations
118+
119+
View SQL statement with
120+
query.ToQueryString()
121+
UseSqlite().LogTo()
122+
123+
### Reading Data
124+
WithNoTracking()
125+
126+
### Creating Data
127+
128+
### Updating Data
129+
130+
### Deleting Data
131+
132+
## Relational Data
133+
134+
Foreign Keys / Navigation property
135+
https://docs.microsoft.com/en-us/ef/core/modeling/relationships
136+
137+
Many to Many
138+
![Many to Many relationship](img/ManyToMany.PNG)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using Microsoft.EntityFrameworkCore;
3+
4+
namespace SampleEntityFramework
5+
{
6+
7+
public class AppDbContext : DbContext {
8+
9+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
10+
{
11+
12+
var connString = "Data Source=appdb.db";
13+
optionsBuilder.UseSqlite(connString);
14+
// .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
15+
16+
base.OnConfiguring(optionsBuilder);
17+
}
18+
19+
public DbSet<BlogPost> Posts { get; set; }
20+
21+
public DbSet<Tag> Tags { get; set; }
22+
23+
}
24+
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Collections.Generic;
2+
3+
namespace SampleEntityFramework
4+
{
5+
public class Author {
6+
7+
public int Id { get; set; }
8+
9+
public string Name { get; set; }
10+
11+
public string TwitterUserName { get; set; }
12+
13+
public IEnumerable<BlogPost> Posts { get; set; }
14+
15+
}
16+
17+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace SampleEntityFramework
6+
{
7+
public class BlogPost {
8+
9+
public int Id { get; set; }
10+
11+
public string Title { get; set; }
12+
13+
public DateTime PublishedUtc { get; set; }
14+
15+
public string Content { get; set; }
16+
17+
public Author Author { get; set; }
18+
19+
public int? AuthorId { get; set; }
20+
21+
public IList<Tag> Tags { get; set; } = new List<Tag>();
22+
23+
public override string ToString() {
24+
25+
var tagsText = "";
26+
if (Tags.Any()) tagsText = $" Tagged with: [{string.Join(',', Tags.Select(t => t.Name))}]";
27+
28+
if (Author == null) return $"{Title} ({Id})" + tagsText;
29+
30+
return $"{Title} ({Id}) - Written By: {Author.Name}" + tagsText;
31+
32+
}
33+
34+
}
35+
36+
}

sessions/0112-EfCore/SampleEntityFramework/Migrations/20201123144404_AddBlogPost.Designer.cs

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)