背景:
我经常遇到这样的情况:我们的ASP.NET页面必须在GridView上向用户显示数据,让他随心所欲地更改它(单元格上的文本框)并且只在实际上将它保存到数据库中点击“保存按钮”。这些数据通常是页面上信息的虚拟状态,这意味着用户可以更改所有内容而无需保存,直到他点击“保存按钮”。
在这些情况下,总是需要在ASP.NET回发中保留数据列表。此数据可以是DataTable
的实例,也可以是List<Someclass>
的实例。
我经常看到人们实现这一点并将数据保存在Session
上。在这种情况下,我通常也会看到一些用户导航时打开多个标签的问题,有些时候在同一页面上。两个不同选项卡的数据合并在一起,导致信息被扰乱的问题。
经常使用Session的示例:
private List<SomeClass> DataList
{
get
{
return Session["SomeKey"] as List<SomeClass>;
}
set
{
Session["SomeKey"] = value;
}
}
人们经常试图通过这样做来解决它:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataList = null
}
else
{
FillGridView(DataList);
}
}
但是当两个标签已经加载并且用户正在更改GridView值并且由于一些奇怪的原因他尝试通过点击另一页上的“保存”按钮来保存数据时呢?我个人不喜欢这个选项。
其他方法是将数据放在ViewState
上。但是,当涉及到持久存在的大型列表时,它可能会严重影响页面存储在页面上(HiddenField
)。
但是,这项工作的最佳方式是什么?有一次,我考虑将Session
与ViewState
一起使用,其中ViewState
将包含唯一标识符,该标识符将对Session
已保存的数据编制索引。这样可以防止在浏览器上的标签之间共享数据:
private List<SomeClass> DataList
{
get
{
if (ViewState["SomeKey"] == null)
{
ViewState["SomeKey"] = Guid.NewGuid().ToString();
}
return Session[ViewState["SomeKey"].ToString()] as List<SomeClass>;
}
set {
if (ViewState["SomeKey"] == null)
{
ViewState["SomeKey"] = Guid.NewGuid().ToString();
}
Session[ViewState["SomeKey"].ToString()] = value;
}
}
另一方面,每次用户进入页面时,它都会向Session存储一个新的数据列表。哪会影响服务器内存。也许他们可能会以某种方式被删除。
问题:
考虑到浏览器上多个标签的上下文,服务器和维护编码团队的成本较低,在Postbacks中保留这类数据的最佳方法是什么?
更新
正如@nunespascal发布的很好,一个选项是使用ViewState
将Session
存储在SessionPageStatePersister
中。但不幸的是,这不是我的选择。然而它与我上一个例子没有什么不同,将数据保存在由ViewState上存储的UniqueId索引的Session上。
还有其他选择吗?
答案 0 :(得分:2)
这个问题有一个简单的解决方案。将ViewState存储在会话中。
为此您需要使用SessionPageStatePersister
您需要做的只是覆盖PageStatePersister
并使用SessionPageStatePersister
而不是默认HiddenFieldPageStatePersister
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(this);
}
}
这甚至可以省去维护唯一密钥的麻烦。隐藏字段将自动用于为每个页面实例保留唯一键。
答案 1 :(得分:0)
我遇到了类似的情况。我们的想法是,如果您允许每个用户使用长会话来更改网格视图,这意味着您还会遇到并发问题,因为最终您只接受对数据进行的最后一组修改。
所以,我的解决方案是允许对数据库进行更改,但要确保所有用户通过SignalR看到相同的状态。
现在,并发问题已经消失,但您仍需要动态进行更改。毕竟,您可能不想保存更改。我通过应用命令设计模式解决了这个问题。现在,任何一组更改都可以被批准或丢弃。每当您检查索引时,您将看到最后批准的gridview。转到更新页面,您会看到实时更新的gridview。另外,请修改以查看旧的已批准的gridview - 命令设计模式的其他优点 - 。