将UserID(表单身份验证)传递给数据库上下文的好方法是什么

时间:2015-03-06 15:50:00

标签: asp.net-mvc asp.net-mvc-5

我想将UserID(Forms Authentication)传递给DB Context类,它将调用SaveChanges()的重载。这个重载函数首先会在calla存储过程中设置DBSession上下文以进行审计,然后调用基类SaveChanges()。

这里的问题是将Controller用户ID发送到此DBContext类(我将UserId作为此类的属性)的一种好方法是什么,而不是每次都显式调用它。 我想要一些每次都会被触发的东西,并将UserId传递给DBContext类,而不是每次都为它编写代码。

    public partial class DataContext : DbContext, IDataContext
{
    public DataContext()
        : base("name=DataContext")
    {
    }

    public DataContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection)
    {

    }

    public string UserID { get; set; }

public override int SaveChanges()
    {
        SetDbSession();
        return base.SaveChanges();
    }

private void SetDbSession()
    {
        //Open a connection to the database so the session is set up
        this.Database.Connection.Open();
        //Set the db session
        //ExecuteSqlCommand ot to be used as it will close the connection
        using (var cmd = this.Database.Connection.CreateCommand())
        {
            var parm = cmd.CreateParameter();
            parm.ParameterName = "@userId";
            parm.Value = UserID ;
            cmd.CommandText = "SetDbSession";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(parm);
            cmd.ExecuteNonQuery();
    };
}

这是数据库上下文类,我想要的只是将UserId传递给它,其方式不会使得使用它变得很麻烦。

2 个答案:

答案 0 :(得分:0)

你可以将它注入构造函数:

public partial class DataContext : DbContext, IDataContext
{
    private string _userID; 
    public DataContext(string userID)
        : base("name=DataContext")
    {
         _userID = userID;
    }

    public DataContext(string userID, DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection)
    {
        _userID = userID;
    }           

    public override int SaveChanges()
    {
        SetDbSession();
        return base.SaveChanges();
    }

    private void SetDbSession()
    {
        //Open a connection to the database so the session is set up
        this.Database.Connection.Open();
        //Set the db session
        //ExecuteSqlCommand ot to be used as it will close the connection
        using (var cmd = this.Database.Connection.CreateCommand())
        {
            var parm = cmd.CreateParameter();
            parm.ParameterName = "@userId";
            parm.Value = _userID;
            cmd.CommandText = "SetDbSession";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(parm);
            cmd.ExecuteNonQuery();
    };
}

在控制器中创建数据库上下文时:

var context = new DataContext(User.Identity.Name);

答案 1 :(得分:0)

如果您正在使用ASP.NET MVC和Autofac,一种方法是通过抽象将HttpContextBase注入服务层。

public class MyHttpAbstraction :IMyHttpAbstraction {
     public MyHttpAbstraction (HttpContextbase httpContextBase) { _httpContextBase = httpContextBase; }
     public string GetUserId() {
          return _httpContextBase.User.Identity.GetUserId();
     }
}

并在您的类型注册中

builder.Register(c => new HttpContextWrapper(HttpContext.Current)).As<HttpContextBase>().InstancePerHttpRequest();

这样,您的服务的具体实现可能依赖于MyHttpAbstraction,而不是直接了解HttpContextBase。您可以将此依赖项一直串到IDataContext。如果你想发疯,可以随意抽象DbContext和IDataContext并创建一个中间类,它将DbContext作为依赖项并实现IDataContext:

public class MyDataContext : IDataContext {
      public MyDataContext(DbContext context, IMyHttpAbstraction myHttpAbstraction) { _context = context; _myHttpAbstraction = myHttpAbstraction; }
//...feel free to implement
}

不确定这是否是您正在寻找的。