Getting Started with Entity Framework Core
Arc provides two approaches for integrating Entity Framework Core into your application:
- Builder Pattern (
WithEntityFrameworkCore) - Recommended when using Arc’sIArcBuilderwith full auto-discovery and observation support - Direct Registration - Flexible approach that works independently of Arc
Builder Pattern (Recommended)
Section titled “Builder Pattern (Recommended)”When using Arc’s application framework, the WithEntityFrameworkCore() extension method provides the most streamlined setup with automatic DbContext discovery and observation support.
Basic Setup
Section titled “Basic Setup”builder.AddCratisArc(configureBuilder: arcBuilder =>{ arcBuilder.WithEntityFrameworkCore(options => { options.ConnectionString = "Server=localhost;Database=MyDb;Trusted_Connection=true"; });});This single configuration:
- Automatically discovers all DbContext types inheriting from
BaseDbContextorReadOnlyDbContext - Registers them with the connection string using appropriate patterns (read-only vs read-write)
- Enables observation support for real-time change notifications
- Applies all Arc conventions (ConceptAs support, entity mapping, etc.)
Configuration Options
Section titled “Configuration Options”The EntityFrameworkCoreOptions class provides the following configuration:
| Property | Type | Default | Description |
|---|---|---|---|
ConnectionString | string | "" | The database connection string. Required for auto-discovery. |
AutoDiscoverDbContexts | bool | true | Whether to automatically discover and register DbContext types. |
JsonConverters | IList<JsonConverter> | [] | Additional System.Text.Json converters merged into JsonConversionOptions at startup. Use this to handle interface-typed or abstract [Json] properties. See JSON Conversion. |
Auto-Discovery
Section titled “Auto-Discovery”When AutoDiscoverDbContexts is enabled (default), the framework automatically:
- Scans for all types inheriting from
BaseDbContext - Identifies which ones are
ReadOnlyDbContextsubtypes - Registers read-only contexts with
AddReadOnlyDbContextWithConnectionString - Registers read-write contexts with
AddDbContextWithConnectionString - Excludes any types marked with
[IgnoreAutoRegistration]
// Your DbContext types - automatically discovered and registeredpublic class OrdersDbContext : BaseDbContext{ public OrdersDbContext(DbContextOptions<OrdersDbContext> options) : base(options) { }
public DbSet<Order> Orders { get; set; }}
public class ReportingDbContext : ReadOnlyDbContext{ public ReportingDbContext(DbContextOptions<ReportingDbContext> options) : base(options) { }
public DbSet<OrderSummary> OrderSummaries { get; set; }}Disabling Auto-Discovery
Section titled “Disabling Auto-Discovery”If you need manual control over DbContext registration, disable auto-discovery:
builder.AddCratisArc(configureBuilder: arcBuilder =>{ arcBuilder.WithEntityFrameworkCore( configureOptions: options => { options.ConnectionString = "Server=localhost;Database=MyDb;Trusted_Connection=true"; options.AutoDiscoverDbContexts = false; }, configureEfCore: efBuilder => { // Manual registration with custom options efBuilder.AddDbContext<OrdersDbContext>((sp, opts) => { opts.EnableSensitiveDataLogging(); }); });});Using the Builder for Manual Registration
Section titled “Using the Builder for Manual Registration”The IEntityFrameworkCoreBuilder provides methods for manual DbContext registration:
arcBuilder.WithEntityFrameworkCore( configureOptions: options => { options.ConnectionString = "Server=localhost;Database=MyDb;Trusted_Connection=true"; options.AutoDiscoverDbContexts = false; }, configureEfCore: efBuilder => { // Use connection string from options efBuilder.AddDbContext<OrdersDbContext>();
// Or specify a different connection string efBuilder.AddDbContext<ArchiveDbContext>("Server=archive;Database=Archive;Trusted_Connection=true"); });Excluding Types from Auto-Discovery
Section titled “Excluding Types from Auto-Discovery”Use the [IgnoreAutoRegistration] attribute to exclude specific DbContext types:
[IgnoreAutoRegistration]public class TestDbContext : BaseDbContext{ // This context won't be auto-registered}Direct Registration (Flexible Approach)
Section titled “Direct Registration (Flexible Approach)”If you’re not using Arc’s builder pattern or need more flexibility, you can register Entity Framework Core support directly on IServiceCollection. This approach doesn’t require the full Arc framework.
Basic Direct Registration
Section titled “Basic Direct Registration”// Add observation services (optional, but recommended)services.AddEntityFrameworkCoreObservation();
// Register your DbContext with connection stringservices.AddDbContextWithConnectionString<OrdersDbContext>( "Server=localhost;Database=MyDb;Trusted_Connection=true");Direct Registration with Options
Section titled “Direct Registration with Options”services.AddDbContextWithConnectionString<OrdersDbContext>( "Server=localhost;Database=MyDb;Trusted_Connection=true", (serviceProvider, options) => { options.EnableSensitiveDataLogging(); options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); });Read-Only DbContext Registration
Section titled “Read-Only DbContext Registration”services.AddReadOnlyDbContextWithConnectionString<ReportingDbContext>( "Server=localhost;Database=MyDb;Trusted_Connection=true");Assembly-Based Discovery
Section titled “Assembly-Based Discovery”For direct registration with assembly scanning:
// Discover and register all ReadOnlyDbContext types from assembliesservices.AddReadModelDbContextsWithConnectionStringFromAssemblies( "Server=localhost;Database=MyDb;Trusted_Connection=true", optionsAction: null, typeof(Program).Assembly, typeof(OrdersDbContext).Assembly);Choosing the Right Approach
Section titled “Choosing the Right Approach”| Feature | Builder Pattern | Direct Registration |
|---|---|---|
| Auto-discovery | ✅ Built-in | ⚠️ Assembly-based only |
| Observation support | ✅ Automatic | ⚠️ Manual setup required |
| Arc integration | ✅ Full | ❌ Not required |
| Flexibility | Good | Maximum |
| Configuration | Centralized | Distributed |
Use Builder Pattern when:
- You’re using Arc’s
IArcBuilderpattern - You want automatic DbContext discovery
- You want observation support without extra configuration
- You prefer centralized configuration
Use Direct Registration when:
- You’re not using the full Arc framework
- You need maximum flexibility in registration
- You’re integrating with an existing application
- You want fine-grained control over each DbContext
Important: Registration Order
Section titled “Important: Registration Order”When using direct registration with observation support, ensure you register observation services before calling AddCratisArc():
// Register observation services firstservices.AddEntityFrameworkCoreObservation();
// Then register your DbContextsservices.AddDbContextWithConnectionString<OrdersDbContext>(connectionString);
// Finally, add Arcbuilder.AddCratisArc();This ensures the singleton IEntityChangeTracker is properly shared across all interceptors.
Note: When using
WithEntityFrameworkCore(), this ordering is handled automatically.
Next Steps
Section titled “Next Steps”- Base DbContext - Learn about the base DbContext class
- Read Only DbContexts - Implement read-only contexts for queries
- Observing DbSet - Create reactive queries with real-time updates
- Entity Mapping - Configure entities using clean patterns