📒
Notes
Cloud ComputingData Science/AIGame Development
  • Home
  • Big O
  • Data Structures & Algorithms
    • Data Structures
      • Array
      • Stack
      • Queue
      • Linked List
      • Binary Tree
    • Algorithms
      • Searching
      • Sorting
      • Graphs
        • Searching
        • Minimum Spanning Tree
        • Shortest Path Algorithms
      • String Algorithms
  • Object Oriented Programming
  • Languages
    • HTML/CSS
      • CSS
    • C++
    • C#
      • Types
      • Keywords
        • Modifiers
          • Access Modifiers
        • Method Parameters
      • Operators and Expressions
      • Collections
      • Constructors
      • Delegates
      • Indexers
      • Concepts
      • Features
        • LINQ
          • Operators
          • Working with Data
          • Methods
          • Resources
        • Asynchronous Programming
        • Reflection
    • Dart
    • GraphQL
    • JavaScript
      • Variable and Parameter
      • Built-in objects
        • Array
        • Built-in Functions
      • Functions
      • Classes
      • Prototype
      • Libraries
        • jQuery
        • React
          • Components
          • State and Lifecycle
          • Hooks
            • useState
            • useEffect
          • Resources
      • Testing Framework
      • Web APIs
    • Kotlin
      • Basics
    • Python
      • Basics
      • Data Structures
      • Functions
      • Resources
        • Flask
    • SQL
      • Basics
      • Operators
      • JOINs
      • Aggregations
      • Subqueries
      • Views
      • Functions
        • Window Functions
      • Stored Procedures
      • Performance Tuning
      • Extras
    • Resources
  • 🌐Web Frameworks
    • Angular
      • Templates
      • Directives
        • Attribute Directives
        • Structural Directives
    • ASP.NET
      • Fundamentals
        • Dependency Injection
        • Middleware
        • Session & State Management
      • Web apps
        • MVC
          • Controllers
            • Filters
          • Models
            • Model Binding
            • Model Validation
          • Views
            • Tag Helpers
            • View Components
          • Features
        • Client-side development
      • Web APIs
        • Controller-based APIs
        • Minimal APIs
        • OpenAPI
        • Content Negotiation
      • SignalR
      • Host and Deploy
        • IIS
      • Security
    • Django
      • The Request/Response Cycle
    • Terminologies
      • Web Server
        • Internet Information Services
    • Resources
  • 📱App Frameworks
    • Introduction
      • Resources
    • Xamarin
      • Lifecycle
      • Custom Renderers & Effects
      • Behaviors
      • Triggers
      • Gestures
      • Commands
      • Dependency Service in XF
      • Libraries
      • Showcase
    • .NET MAUI
      • Controls
      • Navigation
      • Storage Options
  • Multi-Platform Frameworks
    • .NET
      • .NET Framework
        • ADO.NET
        • WCF
      • Fundamentals
        • Logging
        • Testing
      • Advanced
        • Asynchronous Programming
        • Parallel Programming
        • Threading
        • Memory Management
          • Garbage Collection
    • Flutter
  • Object-Relational Mappers
    • Entity Framework
      • Application Models
      • Configuration
      • Setting Up
      • Advanced
  • Databases
    • Introduction
      • DBMS Architecture
      • Normalization
      • Database Transaction Models
    • Relational Databases
      • Microsoft SQL Server
        • Basics
        • Functions
        • Stored Procedures
        • Error Handling
        • Log Shipping
        • Querying and Manipulating JSON data
        • Statements
        • Topics
        • Extras
    • Non-Relational Databases
      • MongoDB
      • Redis
        • Data Structures
        • Introduction
        • Managing Database
  • Tools
    • Version Control
      • Git
        • Setup and Config
        • Basics
          • Sharing and Updating Projects
        • Resources
      • Perforce Helix
    • GitHub
    • Powershell
  • Software Development
    • Software Development Life Cycle
    • Software Design Patterns
      • GoF Design Patterns
      • Architectural Patterns
        • MVC
        • MVVM
        • N-tier Architecture
        • Onion Architecture
        • Data Transfer Objects
      • CQRS
    • Software Design Principles
      • S.O.L.I.D. Priniciple
  • System Design
    • Topics
      • Load Balancing
  • Topics
    • JWT
    • Caching
      • Static vs Dynamic Caching
    • OSI model
      • HTTP
    • Glossary
    • API
      • SOAP
      • REST
    • Microservices
    • WebHooks
    • Practice
    • Operating Systems
      • Windows
    • Architecture
  • 🔖Bookmarks
  • 🔗Resources
Powered by GitBook
On this page
  • The DbContext lifetime
  • DbContextOptions
  • Avoiding DbContext threading issues

Was this helpful?

  1. Object-Relational Mappers
  2. Entity Framework

Configuration

PreviousApplication ModelsNextSetting Up

Last updated 2 years ago

Was this helpful?

The DbContext lifetime

The lifetime of a DbContext begins when the instance is created and ends when the instance is disposed.

A DbContext instance is designed to be used for a single unit-of-work. This means that the lifetime of a DbContext instance is usually very short.

"A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work." -

A typical unit-of-work when using Entity Framework Core (EF Core) involves:

  1. Creation of a DbContext instance

  2. Tracking of entity instances by the context. Entities become tracked by

    1. Being returned from a query

    2. Being added or attached to the context

  3. Changes are made to the tracked entities as needed to implement the business rule

  4. SaveChanges or SaveChangesAsync is called. EF Core detects the changes made and writes them to the database.

  5. The DbContext instance is disposed

  • It is very important to dispose the DbContext after use. This ensures both that any unmanaged resources are freed, and that any events or other hooks are unregistered so as to prevent memory leaks in case the instance remains referenced.

  • DbContext is not thread-safe. Do not share contexts between threads. Make sure to await all async calls before continuing to use the context instance.

  • An InvalidOperationException thrown by EF Core code can put the context into an unrecoverable state. Such exceptions indicate a program error and are not designed to be recovered from.

DbContextOptions

The starting point for all DbContext configuration is DbContextOptionsBuilder. There are three ways to get this builder:

  • In AddDbContext and related methods

  • In OnConfiguring

  • Constructed explicitly with new

Configuring the database provider

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // SQL Server or Azure SQL
        optionsBuilder.UseSqlServer(connectionString);
        // Azure Cosmos DB
        // optionsBuilder.UseCosmos(connectionString, databaseName);
        // SQLite
        // optionsBuilder.UseSqlite(connectionString);
        // EF Core in-memory database
        // optionsBuilder.UseInMemoryDatabase(databaseName);
        // PostgreSQL
        // optionsBuilder.UseNpgsql(connectionString);
        // MySQL/MariaDB*
        // optionsBuilder.UseMySql(connectionString);
        // Oracle
        // optionsBuilder.UseOracle(connectionString);
    }
}

DbContextOptions versus DbContextOptions<TContext>

Most DbContext subclasses that accept a DbContextOptions should use the generic DbContextOptions<TContext> variation.

This ensures that the correct options for the specific DbContext subtype are resolved from dependency injection, even when multiple DbContext subtypes are registered.

public sealed class SealedApplicationDbContext : DbContext
{
    public SealedApplicationDbContext(
        DbContextOptions<SealedApplicationDbContext> contextOptions)
        : base(contextOptions) { }
}

Your DbContext does not need to be sealed, but sealing is best practice to do so for classes not designed to be inherited from.

However, if the DbContext subtype is itself intended to be inherited from, then it should expose a protected constructor taking a non-generic DbContextOptions.

public abstract class ApplicationDbContextBase : DbContext
{
    protected ApplicationDbContextBase(DbContextOptions contextOptions)
        : base(contextOptions) { }
}

This allows multiple concrete subclasses to call this base constructor using their different generic DbContextOptions<TContext> instances.

public sealed class ApplicationDbContext1 : ApplicationDbContextBase
{
    public ApplicationDbContext1(
    DbContextOptions<ApplicationDbContext1> contextOptions)
        : base(contextOptions) { }
}

public sealed class ApplicationDbContext2 : ApplicationDbContextBase
{
    public ApplicationDbContext2(
    DbContextOptions<ApplicationDbContext2> contextOptions)
        : base(contextOptions) { }
}

Notice that this is exactly the same pattern as when inheriting from DbContext directly. That is, the DbContext constructor itself accepts a non-generic DbContextOptions for this reason.

A DbContext subclass intended to be both instantiated and inherited from should expose both forms of constructor.

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> contextOptions)
        : base(contextOptions) { }

    protected ApplicationDbContext(DbContextOptions contextOptions)
        : base(contextOptions) { }
}

Avoiding DbContext threading issues

Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance. This includes both parallel execution of async queries and any explicit concurrent use from multiple threads. Therefore, always await async calls immediately, or use separate DbContext instances for operations that execute in parallel.

When EF Core detects an attempt to use a DbContext instance concurrently, the application will throw an InvalidOperationException.

Always await EF Core asynchronous methods immediately.

Martin Fowler