-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added SentinelValues.csproj * Added sentinel values
- Loading branch information
1 parent
5c3fbf8
commit d65678e
Showing
6 changed files
with
97 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
namespace SentinelValues; | ||
|
||
public class Account | ||
{ | ||
public int Id { get; private set; } | ||
|
||
// One way to use sentinel values is to use a nullable backing field | ||
private int? _balance; | ||
public int Balance | ||
{ | ||
get => _balance ?? 100; | ||
set => _balance = value; | ||
} | ||
|
||
// Another way to use sentinel values is to use a sentinel value that's been configured in ApplicationDbContext | ||
public int Credits { get; set; } = -1; | ||
|
||
public override string ToString() | ||
{ | ||
return $"Id: {Id}, Balance: {Balance}, Credits: {Credits}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Common; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace SentinelValues; | ||
|
||
public class ApplicationDbContext : DbContext | ||
{ | ||
public DbSet<Account> Accounts => Set<Account>(); | ||
|
||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) | ||
{ | ||
optionsBuilder | ||
.UseSqlServer(DbConnectionFactory.Create("SentinelValues")); | ||
} | ||
|
||
protected override void OnModelCreating(ModelBuilder modelBuilder) | ||
{ | ||
modelBuilder.Entity<Account>().Property(a => a.Credits).HasDefaultValue(10).HasSentinel(-1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using Microsoft.EntityFrameworkCore; | ||
using SentinelValues; | ||
|
||
Console.WriteLine("Sentinel Values Sample"); | ||
|
||
using var db = new ApplicationDbContext(); | ||
db.Database.EnsureDeleted(); | ||
db.Database.EnsureCreated(); | ||
|
||
var accounts = new List<Account> | ||
{ | ||
new(), | ||
new() { Balance = 0, Credits = 0 }, // NOTE: Without Sentinel values this would use the defaults of Balance=100, and Credits=10. | ||
new() { Balance = 100, Credits = 10 }, | ||
}; | ||
|
||
db.Accounts.AddRange(accounts); | ||
db.SaveChanges(); | ||
|
||
var allAccounts = db.Accounts.ToList(); | ||
Console.WriteLine("All Account"); | ||
allAccounts.ForEach(Console.WriteLine); | ||
|
||
Console.ReadLine(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Sentinel Values and Database Defaults | ||
|
||
EF Core can configure SQL Server to use Database defaults. For this to work, EF needs to know when NOT to send a value to the DB so that the DB can use the default value. It does this by using the `default` value of the .NET CLR type This works well for reference types, but not value types. | ||
|
||
However, in some cases the CLR default value is a value valid to insert. For example, a default makes sense when creating a record. But what if you want to create a record with the default CLR value? Previously you couldn't. This is where Sentinel Values come in. | ||
|
||
## Use Cases | ||
|
||
- Inserting rows with default CLR values when the DB has a default value | ||
- Correct EF Core behavior when using boolean `default` and `enum` default values | ||
- Overriding defaults for other value types such as `int`, `DateTime`, etc. | ||
|
||
## Resources | ||
|
||
- [EF Core Docs | Sentinel Values and Database Defaults](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#database-defaults-for-enums) |