Net core通用存储库模式如何在编译时注入DbContext而不知道它的类型?

问题描述 投票:1回答:1

我正在开发一个解耦的web api项目,以及在扩展中分离的业务逻辑(分离的项目,这给了我很多项目之间的共享代码),这就是为什么我在数据层上工作也解耦,一切都在工作但唯一让我保持一切的东西是它的AppDbContext.cs

这是一个POC代码,所以你可以得到我的想法(我的问题):

AppDbContext.cs

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> dbContextOptions) : base(dbContextOptions)
    {
    }
}

IEntity.cs

public interface IEntity<TKey>
{
    TKey Id { get; set; }
}

IRepository.cs

public interface IRepository<TEntity, TKey>
    where TEntity : class, IEntity<TKey>
{
    IEnumerable<TEntity> GetAll();
}

GenericRepository.cs

public class GenericRepository<TEntity, TKey> : IRepository<TEntity, TKey>
    where TEntity : class, IEntity<TKey>
{
    private readonly AppDbContext dbContext;

    public GenericRepository(AppDbContext dbContext)
    {
        this.dbContext = dbContext;
    }

    public IEnumerable<TEntity> GetAll()
    {
        return dbContext.Set<TEntity>().ToList();
    }
}

并在组合根中注册它,如下所示:

services.AddScoped(typeof(IRepository<,>), typeof(GenericRepository<,>));

正如您所看到的,我的通用存储库使用AppDbContext,但是如果在另一个被称为不同的项目中呢?或继承自IdentityContext,如何使我的通用存储库,DbContext独立但在启动时也可配置?

更新:

我忘了提到,在某些情况下会有多个DbContext实现。

c# entity-framework generics asp.net-core
1个回答
1
投票

这里最低的公因子是DbContext

Rafactor GenericRepository明确依赖于DbContext

public class GenericRepository<TEntity, TKey> : IRepository<TEntity, TKey>
    where TEntity : class, IEntity<TKey> {
    private readonly DbContext dbContext;

    public GenericRepository(DbContext dbContext) {
        this.dbContext = dbContext;
    }

    public IEnumerable<TEntity> GetAll() {
        return dbContext.Set<TEntity>().ToList();
    }
}

在组合根,您将进行关联

services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(Configuration["database:connectionString"]));

services.AddScoped(typeof(IRepository<,>), typeof(GenericRepository<,>));   
services.AddScoped<DbContext, AppDbContext>();

更新

在多个上下文的情况下,这将需要更多的抽象。在这种情况下,我为每个上下文创建一个特定的抽象。像IDbContextILoggingContext

public interface IDbContext : IDisposable {
    int SaveContext();
    DbSet<TEntity> Set<TEntity>();
    //...other relevant EF members, etc
}

public interface IAppDbContext : IDbContext {

}

public interface ILogDbContext : IDbContext {

}

并让我的DbContext派生类继承自与之相关的类。

public class AppDbContext : DbContext, IAppDbContext {
    public AppDbContext(DbContextOptions<AppDbContext> dbContextOptions) : base(dbContextOptions) {
    }
}

public class LogDbContext : DbContext, ILogDbContext {
    public AppDbContext(DbContextOptions<LogDbContext> dbContextOptions) : base(dbContextOptions) {
    }
}

从那里,通用存储库将明确依赖于相关的抽象

public class GenericRepository<TEntity, TKey> : IRepository<TEntity, TKey>
    where TEntity : class, IEntity<TKey> {
    private readonly IDbContext dbContext;

    public GenericRepository(IAppDbContext dbContext) {
        this.dbContext = dbContext;
    }

    //...code removed for brevity
}

然后在组合根目录下进行必要的配置。

services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(Configuration["database:appConnectionString"]));

services.AddDbContext<LogDbContext>(options =>
    options.UseSqlServer(Configuration["database:logConnectionString"]));

services.AddScoped(typeof(IRepository<,>), typeof(GenericRepository<,>));   
services.AddScoped<IAppDbContext, AppDbContext>();
services.AddScoped<ILogDbContext, LogDbContext>();
© www.soinside.com 2019 - 2024. All rights reserved.