【问题标题】:Configure more than one dbcontext in EF 7在 EF 7 中配置多个 dbcontext
【发布时间】:2015-05-17 06:24:17
【问题描述】:

我用 VS 2015 ctp 创建了一个 web starter 应用程序,我想添加一个内存存储来做一些测试,但是当我尝试读取数据时,我收到了这个消息

数据存储 'SqlServerDataStore' 'InMemoryDataStore' 是 可用的。只能将上下文配置为使用单个数据 店铺。通过重写 OnConfiguring 来配置数据存储 DbContext 类或在 AddDbContext 方法中设置时 服务。

如何创建第二个数据存储?现在我在ConfigureService 方法中有这一行

AddEntityFramework(Configuration)
  .AddSqlServer()
  .AddDbContext<ApplicationDbContext>()
  .AddInMemoryStore()
  .AddDbContext<WorkModel>( options => { options.UseInMemoryStore(persist: true); });

编辑: 好像剧情不太清楚。 我有身份 sql server dbcontext,我想添加第二个 dbcontext,完全分开,我想在内存中运行。我正在研究如何配置两个不同的 dbcontext,在这种情况下使用两个不同的数据存储。

第一个是Identity ApplicationDbContext,另一个是这样的:

public class WorkModel : DbContext
{

    public DbSet<Cliente> Clienti { get; set; }
    public DbSet<Commessa> Commesse { get; set; }

    protected override void OnModelCreating(ModelBuilder builder) {
        builder.Entity<Cliente>().Key(cli => cli.ClienteId);
        builder.Entity<Commessa>().Key(cli => cli.CommessaId);
    }
}

或者你喜欢的任何自定义 dbcontext

【问题讨论】:

  • 上下文的哪一部分只能配置使用单个数据存储你不明白吗?你不能这样做 - 你可以使用 either SQL Server,OR in-memory - 一个或另一个 - 但不能同时使用两者
  • 我要配置第二个数据存储
  • 好吧,错误信息很清楚:这是不可能
  • 你能贴出这两个上下文类的代码吗?现在,您提供的所有内容都表明您有一个上下文类,并且您尝试添加另一个数据库;这里没有任何建议您创建了第二个继承自 DbContext 的类....

标签: c# visual-studio-2015 entity-framework-core


【解决方案1】:

可以将一种DbContext 类型与多个数据存储一起使用。但是,它不适用于您对.AddDbContext() 的调用。这是一个如何将.ConfigureServices() 完全排除在外的示例。

class MyContext : DbContext
{
    bool _useInMemory;

    public MyContext(bool useInMemory)
    {
        _useInMemory = useInMemory;
    }

    protected override void OnConfiguring(DbContextOptions options)
    {
        if (_useInMemory)
        {
            options.UseInMemoryStore(persist: true);
        }
        else
        {
            options.UseSqlServer();
        }
    }
}

然后您可以实例化您的上下文,指定要使用的提供程序。

var inMemoryContext = new MyContext(useInMemory: true);
var sqlServerContext = new MyContext(useInMemory: false);

【讨论】:

  • 谢谢,但老实说,我正在寻找一个更简单的解决方案:两个数据库上下文,一个带有 sql server 数据存储,另一个带有内存数据存储。
  • @LucaMorelli 我不确定你能比这个解决方案简单多少。使用两种不同的上下文会使您的测试毫无意义。
  • 重点不是让相同的 dbContext 有时与 sql server 有时在内存中运行,而是让两个不同的 db 上下文使用不同的数据存储运行
  • 大型数据库上下文可能有很多初始化逻辑 - 所以总是在需要时创建它变得很麻烦。特别是如果每​​次创建新警告或信息消息时都会将每个警告或信息消息输出到控制台。而且 EFCore 现在支持连接池,所以你会失去它。 [我基本上有同样的问题,但我需要一个可配置的超时时间]
【解决方案2】:

你可能需要这样做......

// Add first DbContext here
AddEntityFramework(Configuration)
  .AddSqlServer()
  .AddDbContext<ApplicationDbContext>();

// Add second DbContext here
AddEntityFramework(Configuration)
 .AddInMemoryStore()
 .AddDbContext<WorkModel>(options => { options.UseInMemoryStore(persist: true); });

就我而言,当我需要创建两个 SQL 上下文时,我必须这样做...

AddEntityFramework(Configuration)
  .AddSqlServer()
  .AddDbContext<ApplicationDbContext>()
  .AddDbContext<AnotherDbContext>();

【讨论】:

    【解决方案3】:

    就我而言,我将 Entity Framework Core 1.0.1 与 ASP.NET Core 1.0.1 一起使用,我想在 Windows 和 OS X 上运行相同的项目,但使用不同的数据库。所以这对我有用:

    Startup.cs中添加了一些逻辑:

    public void ConfigureServices(IServiceCollection services)
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("WindowsConnection")));
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlite(Configuration.GetConnectionString("OSXConnection")));
        }
    }
    

    然后在appsettings.json中定义了两个不同的连接字符串:

    "ConnectionStrings":
    {
      "WindowsConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-{dbname}-{dbguid};Trusted_Connection=True;MultipleActiveResultSets=true",
      "OSXConnection": "Data Source=\/Users\/{username}\/Documents\/{projectname}\/bin\/debug\/netcoreapp1.0\/{dbname}.db"
    }
    

    并将此逻辑添加到ApplicationDbContext.cs

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            optionsBuilder.UseSqlite("Filename=./{dbname}.db");
        }
    }
    

    【讨论】:

      【解决方案4】:

      如果你的dbcontext有

      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
              #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
              optionsBuilder.UseSqlServer(<connection string>);
      }
      

      那么你可以通过添加一个守卫来避免双重配置

      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
          if(!optionsBuilder.IsConfigured){
              #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
              optionsBuilder.UseSqlServer(<connection string>);
          }
      }
      

      然后有一个扩展你的 DBContext 的类,它使用内存提供程序,并且你显式地为你的测试实例化。然后你可以传入目标类,避免双重提供者问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-23
        • 2018-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-10
        • 2020-06-05
        • 2018-09-22
        相关资源
        最近更新 更多