首先,我建议您阅读 EntityFramework 在 GitHub 的 wiki 上的
文章。该文章介绍了许多定义
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
和 ApplicationDbContext
类,它们的基类是 DbContext
。最简单的形式只需要:
public class ApplicationDbContext : DbContext
{
}
public class DecAppContext : DbContext
{
}
没有任何DbSet
属性。
第三步。您可以使用Microsoft.Extensions.DependencyInjection
来注入数据库上下文。为此,您只需在Startup.cs
中包含以下内容即可:
public class Startup
{
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection 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)
{
...
}
}
我们需要使用配置"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]
);
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
,并以
[{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}]
的形式返回JSON数据。由于在
ConfigureServices
中使用了
AddJsonOptions
,因此在序列化期间会自动将属性名称从
Id
和
FirstName
转换为
id
和
firstName
。
更新:我必须参考
公告。MVC的下一个版本(RC2)将要求更改上述代码,以使用
[FromServices]
作为附加参数(例如方法
Get()
的附加参数),而不是使用公共属性
[FromServices] public ApplicationDbContext ApplicationDbContext { get; set; }
。您将需要删除属性
ApplicationDbContext
,并向
Get()
方法添加附加参数:
public async IEnumerable<object> Get([FromServices] ApplicationDbContext applicationDbContext) {...}
。这种更改可以轻松完成。请参见
此处以及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>();
}
public DbSet<VignetteModels> VignetteModels { get; set; }
或其他DbSet
是不必要的,但你当然可以使用它。我个人使用存储过程或动态选择生成从Web Api方法返回的数据。ASP.NET 5没有SqlCommand,但Entity Framework 7支持原始SQL查询(通过DbSet.FromSql)和.CreateCommand()
,允许使用纯SQL语句或存储过程。我在代码中演示了如何使用它。/api/users
返回在"SELECT Id, FirstName FROM dbo.Users"
中定义的属性。 - Oleg