I read that Domain project shouldn't specify any ORM. So if I have to create interface for DbContext implemented in Infrastructture project, how can I do it? How can I specify all required DbSet? Interface in Domain project:
public interface IConfigurationDbContext
{
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
Implementation in Infrastructure project:
public class ConfigurationDbContext : DbContext, IConfigurationDbContext
{
public ConfigurationDbContext([NotNull] DbContextOptions<ConfigurationDbContext> options) : base(options)
{
}
public DbSet<Client> Clients { get; set; }
public DbSet<ApiResource> ApiResources { get; set; }
public DbSet<ApiScope> ApiScopes { get; set; }
public DbSet<IdentityResource> IdentityResources { get; set; }
}
As u see, IConfigurationDbContext interface doesn't contain any DbSet, because this way require to specify used ORM in Domain project. So how should I create this interface?
Use IQueryable to create a full-featured abstraction over your DbContext. This preserves the core query-building capabilities of the DbContext, and is easilly substituable by another type using Queryable.AsQueryable.
public interface IConfigurationRepository
{
public IQueryable<Client> Clients { get; }
public IQueryable<ApiResource> ApiResources { get; }
public IQueryable<ApiScope> ApiScopes { get; }
public IQueryable<IdentityResource> IdentityResources { get; }
public void Add<TEntity>(TEntity e);
public void Remove<TEntity>(TEntity e);
public Task<int> SaveChangesAsync();
}
And you can implement this interface instead of having DbSet properties on your DbContext or you can use explicit interface implementation, eg:
public IQueryable<Client> Clients => this.Set<Client>();
public IQueryable<ApiResource> ApiResources => this.Set<ApiResource>();
public IQueryable<ApiScope> ApiScopes => this.Set<ApiScope>();
public IQueryable<IdentityResource> IdentityResources => this.Set<IdentityResource>();
If you remove the DbSet properties, you need to declare your entity types in OnModelCreating like this:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<IdentityResource>();
builder.Entity<ApiResource>();
builder.Entity<ApiScope>();
builder.Entity<Client>();
. . .
}
And when you need the DbSet<TEntity>
get it with
dbContext.Set<TEntity>()