【问题标题】:Connect multiple Databases to .NET core project via Entity Framework Core通过 Entity Framework Core 将多个数据库连接到 .NET Core 项目
【发布时间】:2020-01-27 02:41:21
【问题描述】:

我正在尝试创建一个连接到多个数据库的 .NET 核心应用程序,但使用一个包含所有 CRUD 操作逻辑的通用存储库。实现这一目标的最佳方法是什么?

    public Repository(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
        _set = _dbContext.Set<T>();
    }

上面是我的存储库的构造函数。在这里,我注入了 ApplicationDbContext。我正在寻找一种方法来使这个 ApplicationDbContext 通用,所以我只需要一个存储库,我可以在其中注入不同的上下文来访问多个数据库。基本上我正在寻找这样的东西:

public class Repository_1<T> where T:EntityBase
{
    public Repository_1(IDbContext dbContext)
    {

    }
}

我可以在哪里换出 dbContext 并将其替换为连接到另一个数据库的另一个上下文。

【问题讨论】:

  • 所以在你的场景中你有不同的数据库具有相同的模式?还是每个架构都是独一无二的?
  • 不,每个架构都是唯一的。
  • 所以你本质上想要一个 repo 容器来保存你所有的上下文?
  • 你的意思是这样的:ibb.co/2t9sPqH

标签: c# asp.net-core .net-core entity-framework-core


【解决方案1】:

创建基本上下文并将所有设置包含在此 DBSET 中:

public abstract class BaseContext : DbContext
{
    public BaseContext(DbContext options)
    : base(options)
    { }
    public DbSet<object> FirstDbSet { get; set; }
    ...
}

从 BaseContext 继承两个 DB(数据库):

public class NavaContext : BaseContext
{
    public NavaContext (DbContext<NavaContext> options) : base(options)
    {

    }
}

public class StackContext : BaseContext
{
    public StackContext(DbContext<StackContext> options) : base(options)
    {

    }
}

并在Startup.cs注册:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<NavaContext>(options => options.UseSqlServer(Configuration.GetConnectionString("LATAMConnectionString")));
    services.AddDbContext<StackContext>(options => options.UseSqlServer(Configuration.GetConnectionString("EUConnectionString")));

    // Autofac
    var builder = new ContainerBuilder();

    // needed only if you plan to inject ICollection<BaseContext>
    builder.RegisterType<NavaContext>().As<BaseContext>();
    builder.RegisterType<StackContext>().As<BaseContext>();

    builder.Populate(services);


    return new AutofacServiceProvider(builder.Build());
}

appsettings.json中添加连接字符串:

"ConnectionStrings": {
  "NavaConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "StackConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
}

现在您可以注入两种上下文:

public class ReportRepository : IReportRepository
{
    private readonly NavaContext latamDbContext;
    private readonly StackContext euDbContext;

    public ReportRepository(NavaContext latamDbContext, StackContext euDbContext)
    {
        this.latamDbContext = latamDbContext;
        this.euDbContext = euDbContext;
    }
}

或者如果你打算注入 collection 的上下文:

public class ReportRepository : IReportRepository
{
    private readonly ICollection<BaseContext> dbContexts;

    public ReportRepository(ICollection<BaseContext> dbContexts)
    {
        this.dbContexts = dbContexts;
    }
}

访问特定上下文:

var _stackContext= dbContexts.FirstOrDefault(x => x is StackContext) as StackContext;
var _navaContext= dbContexts.FirstOrDefault(x => x is NavaContext) as NavaContext;

【讨论】:

  • 我能帮你吗?
  • 几乎 - 我实际上希望每种类型都有一个存储库,例如一个用户存储库,我需要连接到正确的数据库(其中包含表 User 的数据库)。我不想要我的存储库中的上下文集合,只有一个。这可能吗?
  • 当然可以。选择一个最佳的存储库方法,您可以定义两个数据库。
  • 你这是什么意思?
【解决方案2】:

您可以为您的存储库设置两个参数并在它们上添加约束,假设您的 dbContext 继承自 DbContext

public class TestRepository<TContext, T> : ITestRepository<TContext,T> 
    where TContext : DbContext
    where T : BaseEntity
{

    private readonly TContext _context;
    private DbSet<T> entities;


    public TestRepository(TContext context)
    {
        _context = context;
        entities = context.Set<T>();
    }



    public List<T> GetAll()
    {

        return entities.AsNoTracking().ToList();
    }
}

ITestReposiroty:

public interface ITestRepository<TContext,T>
    where TContext : DbContext
    where T : BaseEntity
{       
    List<T> GetAll();
}

Startup.cs

services.AddScoped(typeof(ITestRepository<,>), typeof(TestRepository<,>));

控制器:

public class ProductsController : ControllerBase
{
    private readonly ITestRepository<ApplicationDbContext, Product> _repository;

    public TestRepoController(ITestRepository<ApplicationDbContext, Product> repository)
    {
        _repository = repository;
    }
    // GET api/products

    [HttpGet]
    public List<Product> Get()
    {
        return _repository.GetAll();
    }
}

【讨论】:

    【解决方案3】:

    在您的 RepositoryBase 类中:

    public abstract class RepositoryBase<TContext, TEntity>
       where TContext : DbContext
       where Entity: class 
    
    public TContext Context { get; private set; }
    
    public RepositoryBase(TContext context)
    {
        this.Context = context;
    }
    
    public IQueryable<TEntity> GetAll()
    {
            return this.Context.Set<TEntity>().AsNoTracking();
    }
    

    来自特定存储库的使用:

    public class ComputerGroupRepo : RepositoryBase<RequestContext, ComputerGroup> 
    {
        public ComputerGroupRepo()
           : base(new RequestContext())
        {
        }
    
        public IQueryable<ComputerGroup> GetComputerGroups()
        {
            IQueryable<ComputerGroup> result = this.GetAll()
                .Include(v => v.ComputerGroupIps);
    
            return result;
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      BaseRepository 类可以这样使用,它在数据访问层类上使用继承。

      public class GenericRepository<TEntity, TContext> : IGenericRepository<TEntity> 
          where TEntity : class 
          where TContext : DbContext, new()
          {
              private readonly DbContext _context;
              private readonly DbSet<TEntity> _dbSet;
              public GenericRepository()
              {
                  _context = new TContext();
                  _dbSet = _context.Set<TEntity>();
              }
          
          }
      

      数据访问类;

      public class ProductDal:GenericRepository<Product,AppDbContext>,IProductDal
      {
      }
      

      如果使用依赖注入数据访问类必须注册。 Generic Repository 无法注册,因为它在类中实例化。 _context = new TContext();

      【讨论】:

        猜你喜欢
        • 2021-01-07
        • 1970-01-01
        • 2021-10-02
        • 2019-06-27
        • 1970-01-01
        • 1970-01-01
        • 2017-08-04
        • 1970-01-01
        • 2018-01-11
        相关资源
        最近更新 更多