在何处使用依赖注入注册上下文
Where to register the context with dependency injection
根据this教程我应该:
Register your context with dependency injection
教程描述了我应该找到方法
ConfigureServices()
并在其中输入建议的代码。
这是我的 startup.cs:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(MyProject.Startup))]
namespace MyProject
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
所以我不知道该把代码放在哪里。
由于项目不兼容.net core 2.1,需要将Project->属性改为.Net Framework 4.6.1
并安装软件包 Microsoft.EntityFrameworkCore.SqlServer
和 Microsoft.EntityFrameworkCore.Tools
我尝试将依赖项注入添加到 global.asax.cs 文件中,如下所示:
protected void Application_Start()
{
var services = new ServiceCollection();
ConfigureServices(services);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
private void ConfigureServices(IServiceCollection services)
{
var connection = @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;ConnectRetryCount=0";
services.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
}
我成功完成了这一步并创建了控制器并且它可以工作,但是我没有选择正确的上下文 (BloggingContext),所以它创建了第二个数据库。所以,我需要用 BloggingContext 创建一个控制器,你知道怎么做吗?
显示的启动版本和教程相互冲突。
如果这是 Asp.Net 核心 MVC 应用程序,那么您可以自己添加该方法。 Startup
class 是约定的一部分。
public partial class Startup {
//...
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//...
}
}
The ConfigureServices method
The ConfigureServices method is:
- Optional.
- Called by the host before the Configure method to
configure the app's services.
- Where configuration options are set by convention.
但是,如果您尝试在 Asp.Net MVC 5+ (这是 GitHub 项目的目标) 中使用 .Net Core 技术,那么您将需要修改您的方法以适应在非核心平台上使用 .Net Core 依赖注入。
首先,您需要一个 IDependencyResolver
,它是那个版本的 Asp.Net MVC 使用的 DI 框架,以及一种用您自己的解析器替换默认解析器的方法。
public sealed class CoreDependencyResolver : System.Web.Mvc.IDependencyResolver {
private readonly System.Web.Mvc.IDependencyResolver mvcInnerResolver;
private readonly IServiceProvider serviceProvider;
public CoreDependencyResolver(IServiceProvider serviceProvider, System.Web.Mvc.IDependencyResolver dependencyResolver) {
this.serviceProvider = serviceProvider;
mvcInnerResolver = dependencyResolver;
}
public object GetService(Type serviceType) {
object result = this.serviceProvider.GetService(serviceType);
if (result == null && mvcInnerResolver != null)
result = mvcInnerResolver.GetService(serviceType);
return result;
}
public IEnumerable<object> GetServices(Type serviceType) {
IEnumerable<object> result = this.serviceProvider.GetServices(serviceType);
if (result == null && mvcInnerResolver != null)
result = mvcInnerResolver.GetServices(serviceType);
return result ?? new object[0];
}
}
自定义解析器就位后,您现在可以配置应用程序以使用它。
以您当前的示例为起点(评论评论)
protected void Application_Start() {
var services = new ServiceCollection();
ConfigureServices(services);
//build service provider
IServiceProvider provider = services.BuildServiceProvider();
//Get the current resolver used by MVC
var current = DependencyResolver.Current;
//use that and the provider to create your custom resolver
var resolver = new CoreDependencyResolver(provider, current);
//now set the MVC framework to use the resolver that wraps the service provider
//that was created from .Net Core Dependency Injection framework.
DependencyResolver.SetResolver(resolver);
//...
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
private void ConfigureServices(IServiceCollection services) {
//... omitted for brevity (register dependencies as normal)
}
这里我使用的是 Oracle,但你也可以用 SQL Server 做同样的事情...
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkOracle()
.AddDbContext<OracleDbContext>(builder => builder.UseOracle(Configuration["Data:OracleDbContext"]),ServiceLifetime.Scoped)
.AddDbContext<AppsDbContext>(option => option.UseOracle(Configuration["Data:AppsDbConnection:ConnectionString"]), ServiceLifetime.Scoped);
然后在我的 appsettings.json 中包含连接字符串...
"Data": {
"OracleDbContext": "your connection string" },
"AppsDbContext": "your connection string" }
}
虽然使用带有完整框架的 .NET Core 工具效果很好,但如果您必须使用 MVC5 和完整框架,我不会尝试那样做。
.NET 4.6.1依赖注入框架有很多,本例中我将使用Autofac。
- 安装 NuGet 包
Autofac
和 Autofac.Mvc5
。
- 将
AutofacRegistration.cs
class 添加到 App_Start
文件夹
- 在
Global.asax
的 Application_Start()
方法中添加行 AutofacRegistration.BuildContainer();
您的 AutofacRegistration
class 是您连接所有依赖项以进行依赖项注入的地方。完整的文档在这里 https://autofaccn.readthedocs.io/en/latest/integration/mvc.html
public class AutofacRegistration
{
public static void BuildContainer()
{
var builder = new ContainerBuilder();
// Register your MVC controllers
builder.RegisterControllers(typeof(MvcApplication).Assembly);
// Now grab your connection string and wire up your db context
var conn = ConfigurationManager.ConnectionStrings["BloggingContext"];
builder.Register(c => new BloggingContext(conn));
// You can register any other dependencies here
// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
这是假设您的 BloggingContext
有一个将连接字符串作为参数并将其传递给基础 class 的构造函数。像
public class BloggingContext : DbContext
{
public BloggingContext(string connectionString) : base(connectionString)
{
}
}
关于范围等的文档中有更多内容值得一读,但这应该是它的基本要素。
看来您使用的是 .Net Framework,而不是 .Net Core。
这里有 2 个简单的想法:
- 将 DbContext 注入服务层:该层将是 class .Net Framework 库或(如果您的平台是 .Net Core,则使用 .Net Standard Class 库)。此线程向您展示了如何执行它:
- 如果您使用的是 .Net Framework 平台,请使用 Ninject 作为依赖注入器。这个线程显示了一个很好的例子:How to handle DBContext when using Ninject
根据this教程我应该:
Register your context with dependency injection
教程描述了我应该找到方法
ConfigureServices()
并在其中输入建议的代码。
这是我的 startup.cs:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(MyProject.Startup))]
namespace MyProject
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
所以我不知道该把代码放在哪里。
由于项目不兼容.net core 2.1,需要将Project->属性改为.Net Framework 4.6.1
并安装软件包 Microsoft.EntityFrameworkCore.SqlServer
和 Microsoft.EntityFrameworkCore.Tools
我尝试将依赖项注入添加到 global.asax.cs 文件中,如下所示:
protected void Application_Start()
{
var services = new ServiceCollection();
ConfigureServices(services);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
private void ConfigureServices(IServiceCollection services)
{
var connection = @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;ConnectRetryCount=0";
services.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
}
我成功完成了这一步并创建了控制器并且它可以工作,但是我没有选择正确的上下文 (BloggingContext),所以它创建了第二个数据库。所以,我需要用 BloggingContext 创建一个控制器,你知道怎么做吗?
显示的启动版本和教程相互冲突。
如果这是 Asp.Net 核心 MVC 应用程序,那么您可以自己添加该方法。 Startup
class 是约定的一部分。
public partial class Startup {
//...
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//...
}
}
The ConfigureServices method
The ConfigureServices method is:
- Optional.
- Called by the host before the Configure method to configure the app's services.
- Where configuration options are set by convention.
但是,如果您尝试在 Asp.Net MVC 5+ (这是 GitHub 项目的目标) 中使用 .Net Core 技术,那么您将需要修改您的方法以适应在非核心平台上使用 .Net Core 依赖注入。
首先,您需要一个 IDependencyResolver
,它是那个版本的 Asp.Net MVC 使用的 DI 框架,以及一种用您自己的解析器替换默认解析器的方法。
public sealed class CoreDependencyResolver : System.Web.Mvc.IDependencyResolver {
private readonly System.Web.Mvc.IDependencyResolver mvcInnerResolver;
private readonly IServiceProvider serviceProvider;
public CoreDependencyResolver(IServiceProvider serviceProvider, System.Web.Mvc.IDependencyResolver dependencyResolver) {
this.serviceProvider = serviceProvider;
mvcInnerResolver = dependencyResolver;
}
public object GetService(Type serviceType) {
object result = this.serviceProvider.GetService(serviceType);
if (result == null && mvcInnerResolver != null)
result = mvcInnerResolver.GetService(serviceType);
return result;
}
public IEnumerable<object> GetServices(Type serviceType) {
IEnumerable<object> result = this.serviceProvider.GetServices(serviceType);
if (result == null && mvcInnerResolver != null)
result = mvcInnerResolver.GetServices(serviceType);
return result ?? new object[0];
}
}
自定义解析器就位后,您现在可以配置应用程序以使用它。
以您当前的示例为起点(评论评论)
protected void Application_Start() {
var services = new ServiceCollection();
ConfigureServices(services);
//build service provider
IServiceProvider provider = services.BuildServiceProvider();
//Get the current resolver used by MVC
var current = DependencyResolver.Current;
//use that and the provider to create your custom resolver
var resolver = new CoreDependencyResolver(provider, current);
//now set the MVC framework to use the resolver that wraps the service provider
//that was created from .Net Core Dependency Injection framework.
DependencyResolver.SetResolver(resolver);
//...
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
private void ConfigureServices(IServiceCollection services) {
//... omitted for brevity (register dependencies as normal)
}
这里我使用的是 Oracle,但你也可以用 SQL Server 做同样的事情...
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkOracle()
.AddDbContext<OracleDbContext>(builder => builder.UseOracle(Configuration["Data:OracleDbContext"]),ServiceLifetime.Scoped)
.AddDbContext<AppsDbContext>(option => option.UseOracle(Configuration["Data:AppsDbConnection:ConnectionString"]), ServiceLifetime.Scoped);
然后在我的 appsettings.json 中包含连接字符串...
"Data": {
"OracleDbContext": "your connection string" },
"AppsDbContext": "your connection string" }
}
虽然使用带有完整框架的 .NET Core 工具效果很好,但如果您必须使用 MVC5 和完整框架,我不会尝试那样做。
.NET 4.6.1依赖注入框架有很多,本例中我将使用Autofac。
- 安装 NuGet 包
Autofac
和Autofac.Mvc5
。 - 将
AutofacRegistration.cs
class 添加到App_Start
文件夹 - 在
Global.asax
的Application_Start()
方法中添加行AutofacRegistration.BuildContainer();
您的 AutofacRegistration
class 是您连接所有依赖项以进行依赖项注入的地方。完整的文档在这里 https://autofaccn.readthedocs.io/en/latest/integration/mvc.html
public class AutofacRegistration
{
public static void BuildContainer()
{
var builder = new ContainerBuilder();
// Register your MVC controllers
builder.RegisterControllers(typeof(MvcApplication).Assembly);
// Now grab your connection string and wire up your db context
var conn = ConfigurationManager.ConnectionStrings["BloggingContext"];
builder.Register(c => new BloggingContext(conn));
// You can register any other dependencies here
// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
这是假设您的 BloggingContext
有一个将连接字符串作为参数并将其传递给基础 class 的构造函数。像
public class BloggingContext : DbContext
{
public BloggingContext(string connectionString) : base(connectionString)
{
}
}
关于范围等的文档中有更多内容值得一读,但这应该是它的基本要素。
看来您使用的是 .Net Framework,而不是 .Net Core。
这里有 2 个简单的想法:
- 将 DbContext 注入服务层:该层将是 class .Net Framework 库或(如果您的平台是 .Net Core,则使用 .Net Standard Class 库)。此线程向您展示了如何执行它:
- 如果您使用的是 .Net Framework 平台,请使用 Ninject 作为依赖注入器。这个线程显示了一个很好的例子:How to handle DBContext when using Ninject