MVC 6 EF7 RC1 创建多个 dbcontexts [英] MVC 6 EF7 RC1 creating multiple dbcontexts

查看:21
本文介绍了MVC 6 EF7 RC1 创建多个 dbcontexts的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to figure out how to create a second DB context in EF7 RC1. In the past I could use a constructor with :base("connectionName") but that no longer seems an option since it says cannot convert string to System.IServiceProvider.

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

My second context code is as follows:

public class DecAppContext : DbContext
    {

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

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

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

In my config.json I have the connection specified:

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

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

In my configure services section of my startup I have both contexts added:

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

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

The applicationDB context works fine since I can create a user and login without issue

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

However when I try to access the other context as in my controller via:

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

我收到错误:

未配置任何数据库提供程序.通过以下方式配置数据库提供程序在您的 DbContext 类或在设置服务时的 AddDbContext 方法.

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 中具有多个数据库上下文并访问它们的任何工作示例将不胜感激.

Any working examples in EF7 RC1 with multiple db contexts and accessing them would be much appreciated.

推荐答案

首先我会推荐你​​ 来自 GitHub 上 EntityFramework wiki 的文章.本文介绍了多种定义 DbContext 的方法,其中引用了 appsettings.json 的一部分.我个人更喜欢使用 [FromServices] 属性的方式.

First of all I would recommend you the article from the wiki of EntityFramework on GitHub. The article describes many ways to define DbContext, which references to a section of appsettings.json. I personally prefer the way with the usage of [FromServices] attribute.

代码可能如下:

首先你定义了appsettings.json,内容如下

First of all you defined appsettings.json with the following content

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

在这里定义两个连接字符串.

where you define two connection strings.

几秒钟后,您声明了类 DecAppContextApplicationDbContext,它们以 DbContext 作为基类.最简单的形式就是

Seconds you declare the classes DecAppContext and ApplicationDbContext which have DbContext as the base class. The simplest form will be just

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

没有任何 DbSet 属性.

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

Third Step. You use Microsoft.Extensions.DependencyInjection to inject the database contexts. To do this you need just include in Startup.cs something like

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)
    {
        ...
    }
}

Se 创建两个 DbContext(DecAppContextApplicationDbContext)使用配置 "Data:DecAppDbConnectionString" 和 <代码>数据:ApplicationDbConnectionString".

Se create two DbContext (DecAppContext and ApplicationDbContext) using the configuration "Data:DecAppDbConnectionString" and "Data:ApplicationDbConnectionString".

现在我们可以在控制器中使用上下文了.例如

Now we can just use the context in the controller. For example

[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:

or the same using 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;放;} 带有 [FromServices] 属性,ASP.NET 从 ConfigureServices 中注入的上下文初始化它.以同样的方式,您可以在需要时使用第二个上下文 DecAppContext.

One can just declare the property public ApplicationDbContext ApplicationDbContext { get; set; } with the attribute [FromServices] and ASP.NET initialize it from the context injected in ConfigureServices. In the same way one can use the second context DecAppContext whenever you need it.

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

The above code example will execute SELECT Id, FirstName From dbo.Users in the database context and return JSON data in the form [{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}]. The conversion of property names from Id and FirstName to id and firstName will be done automatically during serialization because of usage AddJsonOptions in ConfigureServices.

更新:我必须参考公告.MVC (RC2) 的下一版本将需要更改上述代码以使用 [FromServices] 作为附加参数(例如方法 Get())而不是使用 publicproperty [FromServices] public ApplicationDbContext ApplicationDbContext { get;放;}.需要删除属性 ApplicationDbContext 并向 Get() 方法添加附加参数:public async IEnumerableGet([FromServices] ApplicationDbContext applicationDbContext) {...}.此类更改可以轻松完成.请参阅此处以及MVC演示示例中的更改示例:

UPDATE: I have to reference the announcement. The next version of MVC (RC2) will require to change the above code to use [FromServices] as additional parameter (of method Get() for example) instead of usage public property [FromServices] public ApplicationDbContext ApplicationDbContext { get; set; }. One will need to remove the property ApplicationDbContext and to add additional parameter to Get() method: public async IEnumerable<object> Get([FromServices] ApplicationDbContext applicationDbContext) {...}. Such changes can be easy done. See here and example of the changes in the demo example of 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
    }

这篇关于MVC 6 EF7 RC1 创建多个 dbcontexts的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆