根据登录

时间:2015-10-31 17:02:06

标签: c# asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6

以前是Web Forms应用程序,我在MVC中重写它。

连接名称存储在用户的详细信息中,根据用户的不同,我需要传递不同的连接名称。

WebForms中,这是通过在Session中设置Global.asax变量来解决的,然后每次需要上下文时,我都会在using语句中创建上下文,并通过上下文构造函数中的Session变量如下:

using (IAccountContext db = new MainContext(Session["cn"]) { }

MVC中,我将上下文声明为字段:

public class ManageController : BaseController
{    
    private readonly IAccountContext _db = new MainContext(ConnectionName);

    // other actions

}

我无法传递非静态Session变量。我尝试使用其他控制器将继承的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);
    }
}

我试图避免在每个using中使用Action子句,并依赖MVCDispose方法中处理上下文。

关于如何使这项工作的任何想法?

修改

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

2 个答案:

答案 0 :(得分:1)

RequestContext方法中使用Initialize()

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);
    }
}

答案 1 :(得分:0)

在执行BaseController构造函数并初始化ConnectionName之后,在构造函数中创建MainContext。

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。

我不知道你是否熟悉我在说什么。如果您需要,我可以写更详细的说明。