Session[Constant] vs Session["String Literal"] 性能
我正在检索用户特定的数据,例如ViewData["CartItems"] = Session["CartItems"];
每个请求的键的字符串文字。我应该为此使用常量吗?
如果是,我应该如何实现常用的字符串文字,它会显着影响高流量网站的性能吗?
相关问题未解决 ASP.NET MVC 或Session
.
我正在检索用户特定的数据,例如ViewData["CartItems"] = Session["CartItems"];
每个请求的键的字符串文字。我应该为此使用常量吗?
如果是,我应该如何实现常用的字符串文字,它会显着影响高流量网站的性能吗?
相关问题未解决 ASP.NET MVC 或Session
.
使用该常量,因为如果您输入错误,编译器会给您一个错误,而输入错误的字符串只会给您带来奇怪的错误。
性能差异可能非常小,很难衡量。
使用常量的原因与可维护性有关,而不是性能。无论哪种方式,性能都差不多。
对于字符串文字,您永远无法判断它是否与另一个字符串文字是有意或巧合相同的,因此当需要更改一个字符串时,您不知道要更改哪些其他字符串。但是如果你有常量中的值,你只需在一个地方进行更改。
坏的:
ViewData["username"] = Session["username"];
好的:
const UserNameSessionKey = "username";
const UserNameViewDataKey = "username";
ViewData[UserNameViewDataKey] = Session[UserNameSessionkey];
现在想象一下将会话键的值更改为“userName”,而不想为任何 viewdata 键更改它......
让我们在可维护性方面走得更远。我将引用我关于使用 Session 的其他答案:
假设我们要存储的购物车是我们的 ASP.NET MVC 应用程序的 Session。它将存储在 中Session["ShoppingCart"]
,但我们想要简单的强类型访问和高可测试性:
首先我们定义接口:
public interface ISessionWrapper
{
List<CartItem> ShoppingCart { get; set; }
}
然后我们进行 HttpContext 实现:
public class HttpContextSessionWrapper : ISessionWrapper
{
private T GetFromSession<T>(string key)
{
return (T) HttpContext.Current.Session[key];
}
private void SetInSession(string key, object value)
{
HttpContext.Current.Session[key] = value;
}
public List<CartItem> ShoppingCart
{
get { return GetFromSession<List<CartItem>>("ShoppingCart"); }
set { SetInSession("ShoppingCart", value); }
}
}
GetFromSession 和 SetInSession 是帮助在 Session 中获取和设置数据的方法。它们可以很容易地重用以访问 Session 中的其他字段。
然后我们定义我们的基本控制器(适用于 ASP.NET MVC):
public class BaseController : Controller
{
public ISessionWrapper SessionWrapper { get; set; }
public BaseController()
{
SessionWrapper = new HttpContextSessionWrapper();
}
}
如果要在控制器外使用 Session,只需创建或注入新的 HttpContextSessionWrapper()。
您可以在 Controller 测试中将 SessionWrapper 替换为 ISessionWrapper 模拟,因此它不再依赖于 HttpContext。Session 也更容易使用,因为(List<CartItem>)Session["ShoppingCart"]
你调用而不是调用SessionWrapper.ShoppingCart
。它看起来更好,不是吗?
如果您不使用模型类进行视图并且我认为使用模型类更好,您可以对 ViewData 执行相同操作:
public interface IViewDataWrapper
{
List<CartItem> ShoppingCart { get; set; }
}
public class ViewDataWrapper : IViewDataWrapper
{
}
public class BaseController : Controller
{
public IViewDataWrapper ViewDataWrapper { get; set; }
public BaseController()
{
IViewDataWrapper = new ViewDataWrapper();
}
}
然后简单地在控制器中:
ViewDataWrapper.ShoppingCart = SessionWrapper.ShoppingCart
或者如果您决定不使用 ViewData 和特定模型:
Model.ShoppingCart = SessionWrapper.ShoppingCart
并且只是在视图中(如果您为视图定义基类并引入此接口):
<%= ViewDataWrapper.ShoppingCart %>
或者
<%= Model.ShoppingCart %>
没有输入错误的字符串,强类型,好看。
只是一个简短的说明,但许多更好的示例都有一个包含字符串常量的 SessionKeys 类。这也有助于单元测试,因为您可以在必要时调用单元测试中的常量。
例如(只有一个键,但显然你可以添加更多
public class SessionKeys
{
public const string UserDto = "UserDto";
}
就这样使用(我使用 SessionStateWrapper)
UserDto userDto = _sessionStateWrapper.GetItem(SessionKeys.UserDto) as UserDto;
根据这个关于字典键长度的基准,较短的键更快。在此引用:
较短的查找键是否明显更快?随着键越来越短,查找时间越来越快:
在哪里: