持续到DB的会话

时间:2012-02-06 23:37:06

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

我的架构师想知道为什么我们需要将每个用户的会话持久保存到数据库而不是仅仅使用cookie。我从未见过有人只使用过饼干。

通常我会在Cookie中保存会话ID,然后使用它在键入ID的会话记录上执行CRUD。

我的意思是我没有看到如何在没有proc的情况下进行会话状态。我总是通过自定义表来完成会话状态,该表包含例如IsLoggedIn,IsClosed,IsNew,IPAddress,Browser等常规字段。

有没有人在电子商务网站上完成会话状态而不将其保留在数据库中?

已更新

所以,我们在另一个地方做了一些事情,我在一个电子商务网站工作过,每个月点击次数超过500页:

public USession CreateNewSession(int userID)
{
    string ipAddress = GetCurrentRequestIPAddress(context.Request);

    USession newSession = USession.NewSession();
    newSession.IpAddress = ipAddress;
    newSession.UserID = customerID;
    newSession.Browser = context.Request.UserAgent ?? string.Empty;

    if (context.Request.UrlReferrer != null)
    newSession.Referer = context.Request.UrlReferrer.ToString();
    else
    newSession.Referer = string.Empty;

    InsertSession(newSession);

    return newSession;
}



public USession CreateNewSession(int userID)
{
    string ipAddress = GetCurrentRequestIPAddress(context.Request);

    USession newSession = USession.NewSession();
    newSession.IpAddress = ipAddress;
    newSession.UserID = customerID;
    newSession.Browser = context.Request.UserAgent ?? string.Empty;

    if (context.Request.UrlReferrer != null)
         newSession.Referer = context.Request.UrlReferrer.ToString();
    else
         newSession.Referer = string.Empty;

    InsertSession(newSession);

    return newSession;
}



public USession GetSession()
{
    // existing sessionId this session?
    HttpCookie cookie = context.Request.Cookies["usessionId"];

    if (cookie == null || string.IsNullOrEmpty(cookie.Value))
    session = CreateNewSession(0);
    else
    {
        string sessionID = cookie.Value;

        session = GetSession(sessionID);

        if (session == null) 
            session = CreateNewSession(0);
        else if (session.IsClosed > 0) 
            session = CreateNewSession(session.UserID);
    }

    if (session.LastAccessed < DateTime.Now.AddHours(-1)) session.LoggedIn = false;

    if (session.LastDestination.Equals("lesson"))
        session.LastDestPageDestinationID = ContextValue(context, "lessonid");
    else
        session.LastDestPageDestinationID = 0;

    if (session.IsNew) session.FirstDestination = session.LastDestination;

    SaveSession();

    return session;
}



private void SaveSession()
{
    session.LastAccess = DateTime.Now;
    session.LastDest = string.Empty;

    db.UpdateSession(session);

    if (!cookieIsSet)
    {
        // add a session cookie for this current session
        HttpCookie cookie = CreateSessionCookie("usessionId", session.SessionID, 365);

        if (session.LastDest.Equals("logout", StringComparison.OrdinalIgnoreCase))
            cookie.Value = string.Empty;

        if (session.LastDest.Equals("lessonOrder")) return;

        context.Response.SetCookie(cookie);
    }
}


internal void UpdateSession(USession s)
{
    using (ourConnection conn = CreateConnection("UpdateSession"))
    {
        conn.CommandText = @"update csession set
            closed = @closed,
            userID = @customerID,
            lastAccess = @lastAccess,
            lastDestination = @lastDest,
                        orderId = @OrderId,
            IsloggedIn = @isLoggedIn;

        conn.AddParam("@id", s.Id);
        conn.AddParam("@closed", s.Closed);
        conn.AddParam("@userID", s.UserID);
        conn.AddParam("@lastAccess", s.LastAccess);
        conn.AddParam("@firstDestination", s.FirstDestination);
        conn.AddParam("@lastDestination", s.LastDestination);
        conn.AddParam("@isLoggedIn", s.IsLoggedIn);
        conn.AddParam("@orderID", s.OrderID);

        try
        {
            conn.ExecuteNonQuery();

        }
        catch (Exception ex)
        {
            LogException(ex);
        }
    }
}


public HttpCookie CreateSessionCookie(string cookieValue, string uSessionID, double daysTillExpiration)
{
    HttpCookie cookie = new HttpCookie("usessionid", uSessionID);
    cookie.Expires = DateTime.Now.AddDays(daysTillExpiration);
    cookie.Path = "/";

    return cookie;
}

所以我们在整个代码中使用USession自定义对象来检查loggedIn,强制关闭他们的会话,以及基于当前会话的所有类型的东西。

同样在global.asax的Application_Error中,我们会记录当前的sessionId,以便在出错时进行跟踪。

HttpCookie cookie = Request.Cookies["usessionid"];
if (cookie != null)
{
    logger.Variables = "<b>uSessionID:</b> " + cookie.Value;

    if (cookie.Value.Length > 0)
        logger.USessionID = GetUSessionID(cookie.Value);
}

1 个答案:

答案 0 :(得分:2)

ASP.NET会话有3种可能的状态:

  • 关闭(我的首选) - 根本不使用任何会话
  • InProc - 会话存储在Web服务器的内存中。如果您在Web场中运行,则速度很快但不方便,因为Web场的每个节点都有不同的会话副本,您可能会遇到冲突。
  • Out-of-Proc - 会话存储在运行ASP.NET会话状态Windows服务的专用服务器的内存中。适用于webfarms场景但不够可靠,因为会话仍然存在于某些服务器的内存中,而这些服务器可能无法在崩溃中存活。
  • SQL Server - 会话在SQL Server中保留。非常可靠,适合网络农场。问题在于性能。它将比以前的模式慢,因为会话现在保存在数据库中。

following article中深入介绍了3种模式。

您选择的模式在web.config中配置,它对您的代码完全透明,您只需使用Session["someKey"]来处理会话,它只是不同的底层存储机制。