linking with DB
Configuration
- Table name
- Entity Class name defines Table name
- for example, the
Item
class makesItem
table in DB and thePlayer
class makesPlayer
table in DB - you can define table name by annotation, example,
[Table("Item")]
- Primary Key
- [ClassName]Id is specified by primary key
- you can define primary key by annotation, example,
[Key]
- Foreign Key
- reference another class
- Navigational Property
- when type of the object is outer class type, the object is foreign data
- for example, type of the
Owner
isPlayer
, soOwner
is foreign data - to make foreign key to data, make object name to [ObjectName]Id
- or just use annotation
[ForeignKey("[ObjectName]")]
or[ForeignKEy("[ObjectName]Id")]
- Alternate Key
- not primary key but it is unique, then it can be alternate key
- for example, if
Name
is unique, then it can be alternate key inPlayer
table
- DataModel.cs
EF Core Process
- step
- make DbContext
- search DbSet
- analize modeling class, and search column
- if there is another class which is referenced in modeling class, analize it also
- call OnModelCreating function(extra setting = override)
-
hold all modeling structure of database in inner memory
- DbSet
- notice to EFCore
- ex. there is Items in DB table, and let it reference detail column/ key information on Item class
- DB ConnectionString
- connect DB
- include settings, Authorization, and etc
- SqlServer
- if you use Sql Server, reference
OnConfiguring
method below
- if you use Sql Server, reference
- AppDbContext.cs
Initialize DB
- check exsisting DB
(db.GetService<IDatabaseCreator>() as RelationalDatabaseCreator).Exists()
- EnsuredDeleted()
- Delete Database and ensure it
- EnsuredCreated()
- Create Database and ensure it
- using{}
- to avoid
Disposal()
- to avoid
- DbCommands.cs
CRUD
C(Create)
- AddRange([ListName])
- same function with Add([ObjectName])
- but you can add a bundle of objects in List
- DbCommands.cs
R(Read)
- AsNoTracking
- ReadOnly
- to skip Tracking Snapshot
- Tracking Snapshot
- detect data’s change
- Include
- Eager Loading
- load foreign data by foreign key
- DbCommands.cs
U(Update)
- DbCommands.cs
D(Delete)
- RemoveRange([ListName])
- same function with Remove([ObjectName])
- but you can remove a bundle of objects in List
- DbCommands.cs
Relationship
DB Relationship
- DB relationship modeling
- 1:1
- 1:N
Normally, Foreign Key is N
- N:N
- 1:1
- DataModel.cs
- DbCommands.cs
Loading
Model change
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
Eager Loading
- Pros
- can access DB at once
- Cons
- load all data
- DbCommands.cs
Explicit Loading
- Pros
- can define loading moment
- Cons
- cost of DB access
- DbCommands.cs
Select Loading
- Pros
- loading data which is really needed
- Cons
- need to write in select
ex. SELECT COUNT(*)
- need to write in select
- DbCommends.cs
Data Transfer Object(DTO)
Model change
- DataModel.cs
Select Loading
- Select()
- By DTO, you can make a object instead of
.Select()
- and this solution uses LINQ, so it more easier to write and manage
- By DTO, you can make a object instead of
- IEnumerable
- LINQ to Object
- LINQ to XML Query
- IQueryable
- LINQ to SQL Query
- Extension.cs
- DbCommands.cs
State
State Type
- Detached
- No Tracking
- cannot use SaveChanges()
- Unchanged
- exist in DB, but not change
- not changed from SaveChanges()
- Deleted
- exist in DB, but should be deleted
- apply deleting from SaveChanges()
- Modified
- exist in DB, changed in Client
- apply changing from SaveChanges()
- Added
- not exist in DB
- apply adding from SaveChanges
SaveChanges()
- SaveChanges()
- state of added objects is changed to Unchanged
- manage PK by SQL Identity
- after adding data, received ID and fill Id property of object
- reference Relationship and setting FK and link Object Reference
- link existed player
- first, Tracked Instance
- then, SaveChanges()
State
- DbCommands.cs
Update
Update 3 Step
- Tracked Entity
- change Property of Entity Class(set)
- call SaveChanges
Update
- call SaveChanges
- call DetectChanges innerly
- compare first Snapshot with current Snapshot in DetectChange
- in SQL
Connected vs Disconnected Update
Disconnected
- Disconnected
-
Update
steps occur not at once - this steps are separated
- ex. REST API
-
- Reload method
- send essential data and process 1-2-3 Step
- Full Update method
- send all data and receive
- remake Entity and update
Model Change
- Extentions.cs
Reload
- Pros
- update by minimal data
- Cons
- read twice
- DbCommands.cs
Full
- Pros
- don’t neet to read DB again, update directly
- find data by Primary key, so you don’t need to read original database
- Cons
- need all data
- Security problem(Confidence in the other party)
- JsonConvert
- use Json String in C#
- to make object, use
DeserializeObject
method
- DbCommands.cs by Json
- DbCommands.cs by Object
Foreign Key and Nullable
Relationship
- Principal Entity
- ex. Player
- Dependent Entity
- Foreign Key
- ex. Item
- Policy about Relationship
- Dependent Data can exsist without Principal Data
1) item cannot exsist without player
2) item can exsist without item
- Dependent Data can exsist without Principal Data
- Nullable
- ex. int?
- FK → int → 1)
if player is deleted, item that reference the player is deleted by FK - FK → int? → 2)
if player is deleted, item that reference the player is not deleted by FK
- DbCommands.cs
1) Not Nullable
- DataModel.cs
2) Nullable
- DataModel.cs
Update Relationship
Update Relationship 1:1
- Create new object and remove original data
- Not create new object, just change the data
Update Realtionship 1vN
- Create new object and remove original data
- Not create new object, just change the data
Delete
Model Change
- DataModel.cs
- AppDbContext.cs
- filtering of model level when accessing Item entity
- if want ignore filter, add IgnoreQueryfilters option
SoftDelete
- Delete
- Tracking Entity
- call Remove
- call SaveChanges
- SoftDelte
- not remove the data in DB
- just check that the data is removed
- DbCommands.cs
Configuration
Convention
- Convention
- make form and name with fixed rule, be processed automately in EF Core
- easy and fast, but not include all case
- Entity Class
- public access modifier + non-static
- search and analize public getter during property
- property name = table column name
- name, structure, size
- .NET structure ↔ SQL structure
ex. int, bool - follow Nullable or not of .NET structure
ex. string is nullable
ex. int non-nul vs int? is nullable
- .NET structure ↔ SQL structure
- PK
- define property which name is Id or [ClassName]Id to PK
- Composite Key cannot be defined by Convention
Data Annotation
- add Attribute at class/property
Fluent Api
- set Setting directly in OnModelCreating
-
is the biggest in application range
- DB Column type, size, nullable
Data Annotation | Fluent Api | |
---|---|---|
Nullable | [Required] | .Isrequired |
String length | [MayLength(20)] | .Has MaxLength(20) |
char form | .IsUnicode(true) |
- PK
Data Annotation | Fluent Api | |
---|---|---|
Primary Key | [Key][Column(Order=0)] [Key][Column(Order=1)] | .HasKey(x => new {x.Prop1, x.Prop2}) |
- Index
Data Annotation | Fluent Api | |
---|---|---|
add Index | .HasIndex(p => p.Prop1) | |
add complex index | .HasIndex(p => new {p.Prop1, p.Prop2}) | |
set index name | .HasIndex(p => p.Prop1).HasName("Index_MyProp") | |
add unique Index | .HasIndex(p => p.Prop1).IsUnique() |
- table name
Data Annotation | Fluent Api | |
---|---|---|
DbSet <T > | [Property/Class]name [Table("MyTable")] | .ToTable("MyTable") |
- column name
- in Convention, using [Property]name
Data Annotation | Fluent Api | |
---|---|---|
Column Name<T> | [Column("MyCol")] | .HasColumnName("MyCol") |
- use code modeling, but not in DB modeling(Property and Class)
Data Annotation | Fluent Api | |
---|---|---|
use only in code<T> | [NotMapped] | .Ignore() |
- Soft Delete
Data Annotation | Fluent Api | |
---|---|---|
Soft Delete<T> | .HasQueryFilter() |
- Order
- Convention is the easist
- Validation and related parts → Data Annotation(directly, call SaveChanges)
- etc → Fluent Api
Test
- DataModel.cs
- AppDbContext.cs
Relationship Configuration
- Relationship
- Principal Entity
- Dependent Entity
- Navigational Property
- Primary Key(PK)
- Foreign Key(FK)
- Principal Key = PK or Unique Alternate Key
- Required Relationship(Not-Null)
- Optional Relationship(Nullable)
- Set FK by Convention
- [PrincipalKeyName]
ex. PlayerId - [Class][PrincipalKeyName]
ex. PlayerPlayerId - [NagivationalPropertyName][PrincipalKeyName]
ex. OwnerPlayerId / OwnerId
- [PrincipalKeyName]
FK and Nullable
- Required Relationship(Not-Null)
- when delete, call
OnDelete
factor byCascase
mode → if delete Principal, delete Dependent
- when delete, call
- Optional Relationship(Nullable)
- when delete, call
OnDelete
factor byClientSetNull
mode - if delete Principal and Dependent Tracking, FK is setted null
- if delete Principal and not Dependent Tracking, occur Exception
- when delete, call
Not in Convention
- Complex FK
- several Navigational Property reference same class
- DB or Delete Customizing
Set Relationship with Data Annotation
- [ForeignKey(“Prop1”)]
- [InversProperty]
- several Navigational Property reference same class
Set Relationship with Fluent Api
.HasOne() | .HasMany() | |
.WithOne() | .WithMany() | |
.HasForeignKey() | .IsRequired() | .OnDelete() |
Test
- DataModel.cs
- AppDbContext.cs
Shadow Property & Backing Field
Shadow Property
- in Class OK, but Not in DB
Data Annotation | Fluent Api | |
---|---|---|
only use in code | [NotMapped] | .Ignore() |
- in DB OK, but Not in Class → Shadow Property
Data Annotation | Fluent Api | |
---|---|---|
create | .Property<DateTime>("RecoveredDate") | |
Read/Write | .Property("RecoveredDate").CurrentVale |
Test
- AppDbContext.cs
- DbCommands.cs
Backing Field (EF Core)
- mapping private field in DB and change to public getter to use
- ex. save string by Json type in DB and getter use json with processing
-
Fluent Api in normal
- DataModel.cs
- AppDbContext.cs
Entity ↔ DB Table link
- all Entity Class Read/ Write → Cost (Select Loading, DTO)
Owned Type
- add normal Class in Entity Class
add to same table
- .OwnsOne()
- Relationship .Include() vs Ownership
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
add to diff table
-
.OwnsOne().ToTable()
-
AppDbContext.cs
- DbCommands.cs
Table Per Hiearchy (TPH)
- several classes of hierarchy relation ↔ mapping in one table
ex. Dog, Cat, Bird, Animal
Convention
- first make class by hiearchy and add DbSet
- Discriminator
Test
- DataModel.cs
- AppDbContext.cs
Fluent Api
- .HasDiscriminator().HasValue()
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
Table Splitting
- several entity Class ↔ mapping one table
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
Backing Field & Relationship
Backing Field → mapping private field in DB
- can use in Navigation Property
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
UserDefined Function(UDF)
- The ability to invoke SQL that you create
- want to perform operations on the DB side.
- EF Core queries are inefficient
Steps
- Configuration
- make static function and assign EF Core
- Database Setup
- Use
Test
- DataModel.cs
- Program.cs
- AppDbContext.cs
- DbCommands.cs
Default Value
How to be defined
- defined by Entity Class
- defined by DB Table
- if you use DB by other way except EF ↔ DB, it makes diff
ex) SQL Script
- if you use DB by other way except EF ↔ DB, it makes diff
Auto-Property Initializer(C# 6.0)
- Entity default value
- apply DB by SaveChange
Test
- DataModel.cs
- DbCommands.cs
Fluent Api
- DB Table
- DEFAULT
Test
- AppDbContext.cs
SQL Fragment
- .HasDefaultValueSql
- when add new value, excute in DB
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
Value Generator
- excute in EF Core
- set Generator rule
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
Migration
- EF Core DbContext ↔ need agreement about DB state
Code-First
- the standard is Entity Class or Db Context
-
not always update recently
-
Migration Step
1) make Migration
2) apply Migration - Add-Migration [Name]
1) search DbContext and analize → DB Modeling(recent)
2) DB Modeling most latest Migration state by ModelSnapshot.cs
3) 1-2 Compare and print result
a) ModelSnapshot
b) Migrate.Designer.cs and Migrate.cs -> detail data related with Migration
- Add Up/Down by Hands
- apply Migration
1) SQL change script
- Script-Migration [From] [To] [Options]
2) call Database.Migrate
3) Command Line method
- Update-Database [options]
- Script-Migration [From] [To] [Options]
Test
- DataModel.cs
- Sync to specific Migration
- Update-Database [Name]
- Delete last Migration
- Remove-Migration
Database-First
-
if you have Database, you can make EF Core DbContext from Database
- Download
- Reverse Engineer
- [EF Core Power Tools] - [Reverse Engineer]
SQL-First
- Methods
- Hands Power
- Script-Migration [From] [To] [Options]
- Compare DB and extract SQL
DbContext(Optimize)
ChangeTracker
- Tracking State
- State is mostly intuitive but when it include Relationship, it becames more complexive
Database
- Transaction
- DB Creation / Migration
- Raw SQL
Model
-
DB Modeling
- State Check method
- Entry().State
- Entry().Property().IsModified
- Entry().Navigation().IsModified
- state changing on Add/AddRange
- NotTracking State → Added
- Tracking State → seperated Modified or current state maintain by FK setting
- state changing on Remove/RemoveRange
- (key that made by DB) && (not C# default value) → Updated, Modified or Deleted
-
(not Key that made by DB) (C# default value) → Added - above is Added because of behavior consistency
- DB need to the existence first (ex. Cascade Delete Process)
Test
- DbCommands.cs
- Update/UpdateRange
- the normal method to update Entity in EF is not Update
- Tracked Entity → change property → SaveChanges
- Update is to update all Untracked Entity (Disconnected State)
-
Update Step in EF Core
1) call Update
2) Entity State = Modified
3) all IsModified of Non-Relational Property = true - Relationship in Update
- (key that made by DB) && (not 0 → Updated, Modified or Deleted
-
(not Key that made by DB) (0) → Added
- Attach
- change Untracked Entity to Tracked Entity
- Relationship in Attach
- (key that made by DB) && (not 0 → Unchanged
-
(not Key that made by DB) (0) → Added
Test
- DbCommands.cs
- DbCommands.cs
State Control
- can control State (ex. Optimization)
- Entry().State = EntityState.Added
- Entry().Property(“”).IsModified = true
TrackGraph
- State Control of Untracked Entity in Relationship
ex. change speficific data
ChangeTracker
-
detect state data changing
ex. Print log when name of player changing
ex. Put Validation code
ex. add CreateTime data when player is created time -
Steps
1) override SaveChanges
2) extract / use changing data by ChangeTracker.Entries
Test
- DataModel.cs
- AppDbContext.cs
- DbCommands.cs
call SQL direct
- you can call your SQL
ex. not to LINQ → call Stored Procedure, etc
ex. Performance Optimizing
FormSql → FromSql / FormSqlInterpolated
- Add Raw SQL in EF Core Query
ExecuteSqlCommand → ExcuteSqlRaw / ExecuteSqlInterpolated
- Non-Query SQL(not SELECT)
Reload
- there is Tracked Entity already
- when DB data is changed by ExecuteSqlCommand, then Reload
Test
- DbCommands.cs
Logging
- print SQL log in console
Test
- AppDbContext.cs