Getting Started
This guide introduces the basic DataArc.EntityFrameworkCore execution model.
The setup is:
Install DataArc.EntityFrameworkCore
↓
Create or expose an EF Core execution context
↓
Register the execution context
↓
Inject a command or query factory
↓
Select the execution context
↓
Execute the operation
Prerequisites
You need:
- a supported .NET SDK
- a supported Entity Framework Core version
- an EF Core database provider
- a database connection string
- the DataArc.EntityFrameworkCore NuGet package
The public demo uses SQL Server.
See Compatibility for supported versions.
Install the package
Install DataArc.EntityFrameworkCore in the project that configures persistence:
dotnet add package DataArc.EntityFrameworkCore
Install the EF Core provider required by the application.
For SQL Server:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Choose an execution-context style
DataArc supports two valid styles:
- a public execution-context contract implemented by an internal concrete
DbContext - a concrete
DbContextthat implementsIExecutionContextdirectly
Use a contract when application code should not depend on the concrete persistence implementation.
Use the concrete context directly when hiding it adds no value.
Option 1: Execution-context contract
Create a public contract that extends IExecutionContext:
using DataArc.Core;
using DataArc.EntityFrameworkCore.Demo.Persistence.Database.DBModels;
using Microsoft.EntityFrameworkCore;
namespace DataArc.EntityFrameworkCore.Demo.Persistence.Contracts
{
public interface IGoogleDbContext : IExecutionContext
{
DbSet<Employer>? Employer { get; set; }
DbSet<Employee>? Employee { get; set; }
}
}
Implement the contract with the concrete EF Core DbContext:
using DataArc.EntityFrameworkCore.Demo.Persistence.Contracts;
using DataArc.EntityFrameworkCore.Demo.Persistence.Database.DBModels;
using Microsoft.EntityFrameworkCore;
namespace DataArc.EntityFrameworkCore.Demo.Persistence.Database.DBContexts
{
internal class GoogleDbContext
: DbContext,
IGoogleDbContext
{
public GoogleDbContext(
DbContextOptions<GoogleDbContext> dbContextOptions)
: base(dbContextOptions)
{
}
public DbSet<Employer>? Employer { get; set; }
public DbSet<Employee>? Employee { get; set; }
protected override void OnModelCreating(
ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder
.Entity<Employer>()
.Property(employer => employer.Description)
.HasColumnType("text");
}
}
}
Application workflows target the contract:
.UseDbExecutionContext<IGoogleDbContext>()
Option 2: Direct concrete DbContext
A concrete context can implement IExecutionContext directly:
using DataArc.Core;
using DataArc.EntityFrameworkCore.Demo.Persistence.Database.DBModels;
using Microsoft.EntityFrameworkCore;
namespace DataArc.EntityFrameworkCore.Demo.Persistence.Database.DBContexts
{
public class GoogleDbContext
: DbContext,
IExecutionContext
{
public GoogleDbContext(
DbContextOptions<GoogleDbContext> dbContextOptions)
: base(dbContextOptions)
{
}
public DbSet<Employer>? Employer { get; set; }
public DbSet<Employee>? Employee { get; set; }
protected override void OnModelCreating(
ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder
.Entity<Employer>()
.Property(employer => employer.Description)
.HasColumnType("text");
}
}
}
Application workflows target the concrete context:
.UseDbExecutionContext<GoogleDbContext>()
Register DataArc
Call AddDataArcCore once at the application root.
Register EF Core execution contexts through ConfigureDataArc.
Contract-based registration
services.AddDataArcCore();
services.ConfigureDataArc(dataArc =>
{
dataArc.UseEntityFrameworkCore(ef =>
{
ef.AddDbExecutionContext<
IGoogleDbContext,
GoogleDbContext>(options =>
{
options.UseSqlServer(
configuration.GetConnectionString(
"GoogleDb"));
});
});
});
Direct DbContext registration
services.AddDataArcCore();
services.ConfigureDataArc(dataArc =>
{
dataArc.UseEntityFrameworkCore(ef =>
{
ef.AddDbExecutionContext<GoogleDbContext>(options =>
{
options.UseSqlServer(
configuration.GetConnectionString(
"GoogleDb"));
});
});
});
Execute a query
Inject IQueryFactory into an application service or repository:
private readonly IQueryFactory _queryFactory;
public SalaryAdjustmentService(
IQueryFactory queryFactory)
{
_queryFactory = queryFactory;
}
Create a query and select the execution boundary explicitly:
var employeesQuery = await _queryFactory.CreateQueryAsync();
var employees = await employeesQuery
.UseDbExecutionContext<SolidArcDbContext>()
.ReadWhereAsync<Employee>(
employee => employee.Salary > salaryThreshold);
A contract-based context can be selected in the same way:
var employees = await employeesQuery
.UseDbExecutionContext<IGoogleDbContext>()
.ReadWhereAsync<Employee>(
employee => employee.Rating > 4.5);
Execute a command
Inject ICommandFactory into the application workflow:
private readonly ICommandFactory _commandFactory;
public SalaryAdjustmentService(
ICommandFactory commandFactory)
{
_commandFactory = commandFactory;
}
Create a command builder and add work to an execution context:
var commandBuilder = await _commandFactory
.CreateCommandBuilderAsync();
commandBuilder
.UseDbExecutionContext<GoogleDbContext>()
.AddBulk(employees, batchSize);
Build and execute the command:
var command = await commandBuilder.BuildAsync();
var commandResult = await command.ExecuteAsync();
Execute work across several contexts
A single command pipeline can target several registered execution contexts:
var commandBuilder = await _commandFactory
.CreateCommandBuilderAsync();
commandBuilder
.UseDbExecutionContext<GoogleDbContext>()
.AddBulk(employees, batchSize);
commandBuilder
.UseDbExecutionContext<MicrosoftDbContext>()
.AddBulk(employees, batchSize);
commandBuilder
.UseDbExecutionContext<OpenAIDbContext>()
.AddBulk(employees, batchSize);
var command = await commandBuilder.BuildAsync();
var commandResult = await command.ExecuteAsync();
Each target remains explicit and independently routed.
Check the result
if (!commandResult.Success)
{
throw new InvalidOperationException(
$"Execution failed. {commandResult.Exception?.Message}");
}
return commandResult.TotalAffected;
Next steps
Continue with: