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)
When using Arc's application framework, the WithEntityFrameworkCore() extension method provides the most streamlined setup with automatic DbContext discovery and observation support.
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
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. |
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 registered
public 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
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
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
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)
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
// Add observation services (optional, but recommended)
services.AddEntityFrameworkCoreObservation();
// Register your DbContext with connection string
services.AddDbContextWithConnectionString<OrdersDbContext>(
"Server=localhost;Database=MyDb;Trusted_Connection=true");
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
services.AddReadOnlyDbContextWithConnectionString<ReportingDbContext>(
"Server=localhost;Database=MyDb;Trusted_Connection=true");
Assembly-Based Discovery
For direct registration with assembly scanning:
// Discover and register all ReadOnlyDbContext types from assemblies
services.AddReadModelDbContextsWithConnectionStringFromAssemblies(
"Server=localhost;Database=MyDb;Trusted_Connection=true",
optionsAction: null,
typeof(Program).Assembly,
typeof(OrdersDbContext).Assembly);
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
When using direct registration with observation support, ensure you register observation services before calling AddCratisArc():
// Register observation services first
services.AddEntityFrameworkCoreObservation();
// Then register your DbContexts
services.AddDbContextWithConnectionString<OrdersDbContext>(connectionString);
// Finally, add Arc
builder.AddCratisArc();
This ensures the singleton IEntityChangeTracker is properly shared across all interceptors.
Note: When using
WithEntityFrameworkCore(), this ordering is handled automatically.
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