【问题标题】:Dynamically set entity context according to request url根据请求 url 动态设置实体上下文
【发布时间】:2014-09-10 04:08:32
【问题描述】:

我的 web api 2 应该向客户端提供两个 url:test.mydomain.com 和 production.mydomain.com 当客户端访问测试时,我想为生产 url 实例化测试数据库上下文和生产数据库。

目前我可以手动实例化两者:在控制器内的每个操作上,我可以检查 url 并确定是否加载这个,如果加载那个。 但是我想自动设置数据库,而不检查每个操作的请求 url。我尝试在控制器构造函数中读取请求上下文,但在那个阶段它不存在。

动作过滤器? OnAction 执行?但是我如何在过滤器中实例化它并在控制器操作中使用它呢?还有什么建议吗?

【问题讨论】:

  • 对于DI / IOC 来说听起来不错。
  • 这听起来比它需要的复杂得多。您的数据库架构在您的测试环境和生产环境中是否相同(如果它们不同,则无法达到目的)。如果是这样,只需为连接到正确数据库的每个环境使用 Web.config。
  • 嗨贾斯汀,这不是不同环境的问题。它是相同的应用程序,相同的控制器。唯一的事情是我需要在运行时根据请求 url 设置实体上下文。我不想复制整个代码。
  • 如果您想避免任何过度设计,您可以简单地使用 factory,它会接收当前 URL 并提供正确的 DbContext,然后在您的请求处理开始时您只需写:using (MyContext context = ContextFactory.Get(currentUrl)){ ... }

标签: asp.net entity-framework asp.net-web-api routing


【解决方案1】:

正如 Erik 所说,这可以使用依赖注入相当容易地解决。

  1. 将上下文的创建封装在负责根据 url 参数创建上下文的工厂后面
  2. 创建一个委托处理程序来检查请求并使用上下文工厂根据当前 url 实例化一个新上下文
  3. 将上下文缓存在缓存对象中,其生命周期范围为当前 api 请求
  4. 使用上下文缓存对象检索存在于 api 请求生命周期范围内的所有类型的 url 特定上下文

这是一个使用 AutoFac 的示例:

public interface IContextCache
{
    DbContext CurrentContext { get; set; }
}

// This will be wired as instance per api request
// and hence return the same context across the entire
// request from handler to controller
public class ContextCache : IContextCache
{
    public DbContext CurrentContext { get; set; }
}

public interface IContextFactory
{
    DbContext Create(Uri requestUri);
}

public class ContextFactory : IContextFactory
{
    public DbContext Create(Uri requestUri)
    {
        return CreateContextBasedOnUri(requestUri);
    }
}

// This is fired before the controller and creates and caches
// as per url context
public class ContextHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
        CancellationToken cancellationToken)
    {
        var dependencyScope = request.GetDependencyScope();
        var contextFactory = (IContextFactory)dependencyScope.GetService(typeof(IContextFactory));       
        var contextCache = (IContextFache)dependencyScope.GetService(typeof(IContextCache));
        var context = contextFactory.Create(request.RequestUri);
        contextCache.CurrentContext = context;
        return base.SendAsync(request, cancellationToken);
    }
}

// Uses the per api request scoped cache to retrieve the 
// correct context
public class MyController : ApiController
{
    public MyController(IContextCache contextCache)
    {
        var context = contextCache.CurrentContext;
    }
}

// AutoFac wiring
// Perform boiler plate AutoFac registration for WebApi
// (See AutoFac documentation)

// Custom registrations
builder.RegisterType<ContextCache>()
    .As<IContextCache>()
    .InstancePerApiRequest();
builder.RegisterType<ContextFactoy>()
    .As<IContextFactory>()
    .InstancePerDependency();

// Handler registration
public static void Register(HttpConfiguration config)
{
    config.MessageHandlers.Add(new ContextHandler());
}

【讨论】:

  • 为什么contextFactory 在上下文处理程序中为空?
猜你喜欢
  • 2014-06-14
  • 2014-04-19
  • 2015-02-08
  • 2021-05-03
  • 2018-09-27
  • 2021-08-10
  • 2013-04-05
  • 2011-03-06
  • 1970-01-01
相关资源
最近更新 更多