asp.net-web-api – Web Api的动态连接字符串
我通过web api公开我的存储库操作.存储库已使用实体框架和工作单元模式实现.我有很多相同数据库的实例.每个代表不同客户的数据.现在的问题是如何通过每个webapi调用动态设置连接字符串?我应该每次调用都获得连接字符串参数吗?或者我应该为每个客户端托管网络Api?
解决方法
根据提供的信息,我将使用相同的控制器并查找连接字符串,而不是为每个客户端托管单独的Web API实例.托管多个实例会有更多的复杂性,并且给出的唯一区别是连接字符串,我不认为复杂性是合理的.
我们需要做的第一件事是确定调用哪个客户端以获取适当的连接字符串.这可以通过令牌,标题,请求数据或路由来完成.路由是最简单的,最常见的是客户端可访问,所以我将演示使用它;但是,在决定如何做出决定时,请仔细考虑您的要求. [Route( "{clientId}" )] public Foo Get( string clientId ) { /* ... */ } 接下来,我们需要为客户端获取正确的DbContext.我们希望继续使用DI,但这很复杂,因为在创建Controller之后我们才知道构造对象需要什么连接字符串.因此,我们需要注入某种形式的工厂而不是对象本身.在这种情况下,我们将其表示为Func< string,IUnitOfWork>理解它将’clientId’作为一个字符串并返回一个适当实例化的IUnitOfWork.我们也可以使用命名接口. [RoutePrefix("foo")] public class FooController : ApiController { private Func<string,IUnitOfWork> unitOfWorkFactory; public FooController( Func<string,IUnitOfWork> unitOfWorkFactory ) { this.unitOfWorkFactory = unitOfWorkFactory; } [Route( "{clientId}" )] public Foo Get( string clientId ) { var unitOfWork = unitOfWorkFactory(clientId); // ... } } 剩下的就是配置我们的依赖注入容器,为我们提供Func< string,IUnitOfWork>.实施之间可能会有很大差异.以下是在Autofac中执行此操作的一种可能方法. protected override void Load( ContainerBuilder builder ) { // It is expected `MyDbContext` has a constructor that takes the connection string as a parameter // This registration may need to be tweaked depending on what other constructors you have. builder.Register<MyDbContext>().ForType<DbContext>().InstancePerRequest(); // It is expected `UnitOfWork`'s constructor takes a `DbContext` as a parameter builder.RegisterType<UnitOfWork>().ForType<IUnitOfWork>().InstancePerRequest(); builder.Register<Func<string,Bar>>( c => { var dbContextFactory = c.Resolve<Func<string,DbContext>>(); var unitOfWorkFactory = c.Resolve<Func<DbContext,IUnitOfWork>>(); return clientId => { // You may have injected another type to help with this var connectionString = GetConnectionStringForClient(clientId); return unitOfWorkFactory(dbContextFactory(connectionString)); }; }); } 使用Autofac是因为注释表明当前正在使用Autofac,尽管其他容器也可以获得类似的结果. 有了这个,控制器应该能够被实例化,并且每个请求都将使用适当的连接字符串. 基于链接项目的示例注册: builder.Register<Func<string,IEmployeeService>>( c => { var dbContextFactory = c.Resolve<Func<string,IMainContext>>(); var unitOfWorkFactory = c.Resolve<Func<IMainContext,IUnitOfWork>>(); var repositoryFactory = c.Resolve<Func<IMainContext,IEmployeeRepository>>(); var serviceFactory = c.Resolve<Func<IUnitOfWork,IEmployeeService>>(); return clientId => { // You may have injected another type to help with this var connectionString = GetConnectionStringForClient(clientId); IMainContext dbContext = dbContextFactory(connectionString); IUnitOfWork unitOfWork = unitOfWorkFactory(dbContext); IEmployeeRepository employeeRepository = repositoryFactory(dbContext); unitOfWork.employeeRepositoty = employeeRepository; return serviceFactory(unitOfWork); }; }); 如果您发现注册变得过于繁琐,因为需要手动进行一些连接,您可能需要在确定客户端后查看更新(或创建新的)容器,以便您可以更多地依赖容器. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc-4 – DataAnnotation的必需属性
- asp.net-mvc – MVC 4:强制ScriptBundle返回Javascript文件
- ASP.NET – 从不调用以编程方式创建的按钮的事件处理程序
- asp.net-mvc – ASP.NET MVC:奇怪的POST行为
- ASP.NET自定义错误,除了404错误,
- asp.net – MVC中的HTTPContext和Controllercontext
- 如何使用ASP.NET在纯HTML页面上执行表单验证?
- 通过ASP.NET运行时将IIS7配置为服务器静态内容
- asp.net-mvc-5 – ASP.NET MVC中Controller的模型对象列表的
- 什么是部署ASP.Net Web应用程序的好方法?
- ASP.NET:asp:禁用Javascript的LinkBut??ton?
- asp.net-mvc – 通过集合迭代并在Razor中打印索引
- asp.net-mvc – 具有相同签名的ASP.NET MVC 1.0控
- 您能以编程方式更改ASP.NET中的会话超时吗?
- 如何在Asp.Net中使用CSS创建多列数据输入表单?
- asp.net – 在资源文件中使用HTML
- asp.net-mvc – asp.net mvc中的加密视图状态
- asp.net-mvc – 控制器中的模拟服务器
- asp.net – 为什么即使我将EnableViewState设置为
- 如何在ASP.NET Core 2.0中设置多个身份验证方案?