MVC 6 EF7 RC1 创建多个 dbcontext
MVC 6 EF7 RC1 creating multiple dbcontexts
我正在尝试弄清楚如何在 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 上下文工作正常,因为我可以毫无问题地创建用户和登录
然而,当我尝试通过以下方式访问我的控制器中的其他上下文时:
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"
}
}
在其中定义两个连接字符串。
你声明 classes DecAppContext
和 ApplicationDbContext
的秒数,它们以 DbContext
作为基础 class。最简单的形式就是
public class ApplicationDbContext : DbContext
{
}
public class DecAppContext : DbContext
{
}
没有任何 DbSet
属性。
第三步。您使用 Microsoft.Extensions.DependencyInjection
注入数据库上下文。为此,您只需在 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)
{
...
}
}
Se 使用配置 "Data:DecAppDbConnectionString"
和 "Data:ApplicationDbConnectionString"
.
创建两个 DbContext
(DecAppContext
和 ApplicationDbContext
)
现在我们可以在控制器中使用上下文了。例如
[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;
}
}
}
可以只用 [FromServices]
属性声明 属性 public ApplicationDbContext ApplicationDbContext { get; set; }
,然后 ASP.NET 从 ConfigureServices
中注入的上下文对其进行初始化。以同样的方式,您可以在需要时使用第二个上下文 DecAppContext
。
上面的代码示例将在数据库上下文中执行SELECT Id, FirstName From dbo.Users
和return JSON 形式的数据[{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}]
。由于 AddJsonOptions
在 ConfigureServices
.
更新: 我必须参考 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 和 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
}
我正在尝试弄清楚如何在 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 上下文工作正常,因为我可以毫无问题地创建用户和登录
然而,当我尝试通过以下方式访问我的控制器中的其他上下文时:
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"
}
}
在其中定义两个连接字符串。
你声明 classes DecAppContext
和 ApplicationDbContext
的秒数,它们以 DbContext
作为基础 class。最简单的形式就是
public class ApplicationDbContext : DbContext
{
}
public class DecAppContext : DbContext
{
}
没有任何 DbSet
属性。
第三步。您使用 Microsoft.Extensions.DependencyInjection
注入数据库上下文。为此,您只需在 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)
{
...
}
}
Se 使用配置 "Data:DecAppDbConnectionString"
和 "Data:ApplicationDbConnectionString"
.
DbContext
(DecAppContext
和 ApplicationDbContext
)
现在我们可以在控制器中使用上下文了。例如
[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;
}
}
}
可以只用 [FromServices]
属性声明 属性 public ApplicationDbContext ApplicationDbContext { get; set; }
,然后 ASP.NET 从 ConfigureServices
中注入的上下文对其进行初始化。以同样的方式,您可以在需要时使用第二个上下文 DecAppContext
。
上面的代码示例将在数据库上下文中执行SELECT Id, FirstName From dbo.Users
和return JSON 形式的数据[{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}]
。由于 AddJsonOptions
在 ConfigureServices
.
更新: 我必须参考 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 和 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
}