设置上下文';的连接名称,具体取决于登录的用户
本文关键字:取决于 用户 登录 上下文 连接 设置 | 更新日期: 2023-09-27 18:19:58
这曾经是一个Web Forms
应用程序,我正在MVC中重写它。
连接名称存储在用户的详细信息中,根据用户的不同,我需要传递不同的连接名称。
在WebForms
中,这是通过在Global.asax
中设置Session
变量来解决的,然后每次需要上下文时,我都会在using语句中创建上下文,在上下文构造函数中传递Session
变量,如下所示:
using (IAccountContext db = new MainContext(Session["cn"]) { }
在MVC
中,我将上下文声明为一个字段:
public class ManageController : BaseController
{
private readonly IAccountContext _db = new MainContext(ConnectionName);
// other actions
}
并且我不能传递非静态的CCD_ 7变量。我尝试使用其他控制器将继承的BaseController
,并尝试在构造函数和Initialize方法中初始化ConnectionName
,但都不起作用
public class BaseController : Controller
{
public BaseController()
{
using (var db = new UserDbContext())
{
ConnectionName = (db.Users.Find(User.Identity.GetUserId())).ConnectionString;
}
}
public static string ConnectionName { get; set; }
protected override void Initialize(RequestContext requestContext)
{
using (var db = new UserDbContext())
{
ConnectionName = (db.Users.Find(User.Identity.GetUserId())).ConnectionString;
}
base.Initialize(requestContext);
}
}
我试图避免在每个Action
中使用using
子句,并依靠MVC
在Dispose
方法中处理上下文。
有什么想法可以让它发挥作用吗?
编辑:
Francesc Castells的答案看起来很有希望,但当使用BaseController
时,User.Identity.GetUserID()
调用会抛出一个NullReference异常。如果ManageController继承了原来的Controller
,它就可以正常工作。我是不是忘记初始化其他东西了?
这是Stacktrace
[NullReferenceException: Object reference not set to an instance of an object.]
TestProj.Web.Controllers.BaseController..ctor() in E:'TestProj.Web'Controllers'BaseController.cs:14
TestProj.Web.Controllers.ManageController..ctor() in E:'TestProj.Web'Controllers'ManageController.cs:60
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +119
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
System.Activator.CreateInstance(Type type) +11
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55
[InvalidOperationException: An error occurred when trying to create a controller of type 'TestProj.Web.Controllers.ManageController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +76
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +88
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +194
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
在Initialize()
方法中使用RequestContext
。
public class BaseController : Controller
{
protected string _connectionName;
protected override void Initialize(RequestContext requestContext)
{
if(requestContext.HttpContext.User.Identity.IsAuthenticated)
{
using (var db = new UserDbContext())
{
_connectionName = db.Users.Find(
requestContext.HttpContext.User.Identity.GetUserId())
.ConnectionString;
}
}
base.Initialize(requestContext);
}
}
现在你可以简单地继承你的控制器:
public class ManageController : BaseController
{
private IAccountContext _db
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
_db = new MainContext(_connectionName);
}
public ActionResult MyAction()
{
// now you have access _db variable
}
protected override void Dispose(bool disposing)
{
if(disposing)
{
_db.Dispose();
}
base.Dispose(disposing);
}
}
public class ManageController : BaseController
{
private readonly IAccountContext _db;
public ManageController()
{
// Here the base constructor has already been executed, so ConnectionName has the right value
_db = new MainContext(ConnectionName);
}
// other actions
}
但我建议一种不同的方法:将依赖注入与IoC一起使用,例如Unity。向InjectionFactory注册您的IAccountContext,这将是一个简单的方法,它将运行您已经拥有的代码,以获得基于User.Identity.GetUserId()的连接字符串,并创建传递发现的连接字符串的AccountContext。
我不知道你是否熟悉我说的话。如果你需要,我可以写更详细的说明。