asp.net-core-mvc - MVC 6 EF7 RC1 创建多个 dbcontext

标签 asp.net-core-mvc entity-framework-core

我正在尝试弄清楚如何在 EF7 RC1 中创建第二个数据库上下文。过去,我可以使用带有 :base("connectionName") 的构造函数,但这似乎不再是一个选项,因为它说无法将字符串转换为 System.IServiceProvider。

我的第二个上下文代码如下:

public class DecAppContext : DbContext
    {

        public DecAppContext()
          //  :base("DefaultConnection")
        {

        }
        public DbSet<VignetteModels> VignetteModels { get; set; }
        public DbSet<VignetteResult> Result { get; set; }
    }
}

在我的 config.json 中,我指定了连接:

"Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-xxxxx...;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  }

在我的启动的配置服务部分中,我添加了两个上下文:

services.AddEntityFramework()
                .AddSqlServer()
                .AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]))
                .AddDbContext<DecAppContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

applicationDB 上下文工作正常,因为我可以毫无问题地创建用户并登录

但是,当我尝试通过以下方式访问 Controller 中的其他上下文时:

private DecAppContext db = new DecAppContext();
var vignette = db.VignetteModels.SingleOrDefault(v => v.CaseId == vid);

我收到错误:

No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.

EF7 RC1 中具有多个数据库上下文并访问它们的任何工作示例将不胜感激。

最佳答案

首先,我会向您推荐来自 GitHub 上 EntityFramework wiki 的 the article。本文描述了定义 DbContext 的多种方法,其中引用了 appsettings.json 的一部分。我个人更喜欢使用 [FromServices] 属性的方式。

代码可能如下:

首先,您使用以下内容定义了 appsettings.json

{
  "Data": {
    "ApplicationDbConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ApplicationDb;Trusted_Connection=True;MultipleActiveResultSets=true",
    "DecAppDbConnectionString": "Server=Server=(localdb)\\mssqllocaldb;Database=DecAppDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

在其中定义两个连接字符串。

接下来声明以 DecAppContext 作为基类的 ApplicationDbContextDbContext 类。最简单的形式就是

public class ApplicationDbContext : DbContext
{
}
public class DecAppContext : DbContext
{
}

没有任何 DbSet 属性。

第三步。您使用 Microsoft.Extensions.DependencyInjection 注入(inject)数据库上下文。为此,您只需在 Startup.cs 中包含类似

public class Startup
{
    // property for holding configuration
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddEnvironmentVariables();
        // save the configuration in Configuration property
        Configuration = builder.Build();
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc()
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options => {
                options.UseSqlServer(Configuration["Data:ApplicationDbConnectionString"]);
            })
            .AddDbContext<DecAppContext>(options => {
                options.UseSqlServer(Configuration["Data:DecAppDbConnectionString"]);
            });
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ...
    }
}

使用配置 DbContextDecAppContext 创建两个 ApplicationDbContext ( "Data:DecAppDbConnectionString""Data:ApplicationDbConnectionString" )。

现在我们可以只使用 Controller 中的上下文了。例如

[Route("api/[controller]")]
public class UsersController : Controller
{
    [FromServices]
    public ApplicationDbContext ApplicationDbContext { get; set; }

    [FromServices]
    public DecAppContext DecAppContext { get; set; }

    [HttpGet]
    public IEnumerable<object> Get() {
        var returnObject = new List<dynamic>();

        using (var cmd = ApplicationDbContext.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "SELECT Id, FirstName FROM dbo.Users";
            if (cmd.Connection.State != ConnectionState.Open)
                cmd.Connection.Open();

            var retObject = new List<dynamic>();
            using (var dataReader = cmd.ExecuteReader())
            {
                while (dataReader.Read())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
                        dataRow.Add(
                            dataReader.GetName(iFiled),
                            dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
                        );

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

或使用 async/await 进行相同操作:

[Route("api/[controller]")]
public class UsersController : Controller
{
    [FromServices]
    public ApplicationDbContext ApplicationDbContext { get; set; }

    [FromServices]
    public DecAppContext DecAppContext { get; set; }

    [HttpGet]
    public async IEnumerable<object> Get() {
        var returnObject = new List<dynamic>();

        using (var cmd = ApplicationDbContext.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "SELECT Id, FirstName FROM dbo.Users";
            if (cmd.Connection.State != ConnectionState.Open)
                cmd.Connection.Open();

            var retObject = new List<dynamic>();
            using (var dataReader = await cmd.ExecuteReaderAsync())
            {
                while (await dataReader.ReadAsync())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
                        dataRow.Add(dataReader.GetName(iFiled), dataReader[iFiled]);

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

只需使用属性 public ApplicationDbContext ApplicationDbContext { get; set; } 声明属性 [FromServices] 即可,ASP.NET 从注入(inject) ConfigureServices 的上下文中初始化它。以同样的方式,您可以在需要时使用第二个上下文 DecAppContext

上面的代码示例将在数据库上下文中执行 SELECT Id, FirstName From dbo.Users 并以 [{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}] 形式返回 JSON 数据。由于在 Id 中使用了 FirstName,属性名称从 idfirstNameAddJsonOptionsConfigureServices 的转换将在序列化期间自动完成。

更新:我必须引用 the announcement 。 MVC 的下一个版本(RC2)将需要更改上述代码以使用 [FromServices] 作为附加参数(例如方法 Get() ),而不是使用公共(public)属性 [FromServices] public ApplicationDbContext ApplicationDbContext { get; set; } 。我们需要删除属性 ApplicationDbContext 并向 Get() 方法添加附加参数: public async IEnumerable<object> Get([FromServices] ApplicationDbContext applicationDbContext) {...} 。这样的改变很容易完成。请参阅 here 和 MVC 演示示例中的更改示例:

[Route("api/[controller]")]
public class UsersController : Controller
{
    [HttpGet]
    public async IEnumerable<object> Get(
                     [FromServices] ApplicationDbContext applicationDbContext,
                     [FromServices] DecAppContext decAppContext)
    {
        var returnObject = new List<dynamic>();

        // ...  the same code as before, but using applicationDbContext 
        // and decAppContext parameters instead of ApplicationDbContext
        // and DecAppContext properties
    }

关于asp.net-core-mvc - MVC 6 EF7 RC1 创建多个 dbcontext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34161278/

相关文章:

angularjs - 使用 Angular 进行基于 ViewModel 的验证

c# - 如何将数据从 AuthorizationHandler 传递到 Asp.net Core 中的 Controller

vue.js - 客户端深度链接与 WebpackDevMiddleware 404s

asp.net-mvc - ASP.NET 5 IsPost 消失了吗?

asp.net-core - .Net CORE Dapper 连接字符串?

c# - 多列的 EF 值转换

c# - Entity Framework Core 中 TimeSpan 的总和

entity-framework-core - NoSQL 与 Entity Framework 核心

c# - 为什么运行时表达式会导致 Entity Framework Core 5 的缓存发生冲突?

c# - 使用 EF Core 防止同步 API 使用