我在这里发现了许多关于在viewstate中存储值的问题,但是没有找到一个好的答案。
我遇到从数据库中检索大量数据的情况。然后我根据我的需要过滤和操作数据(所以这是一个非常重要的过程)。然后我将结果放在自定义类列表中。例如,假设这个类将是Person
List<Person> persons = new List<Person>();
private void FillPersons()
{
//Call to webservice
persons = ws.GetPersonsList();
//Do all kind of custom filtering
//Manipulate the data
}
现在整个FillPersons()
方法是一个繁重的过程,返回非常少量的数据。不幸的是,它无法移动到SQL,并且在这个过程中沉重,但这不是重点。
关键是我需要在帖子后面的页面上重复使用这些数据。
现在为了节省对FillPersons()
的额外调用我将Person类标记为可序列化并将列表存储在视图状态中,除了由于视图状态页面变为1mb大小这一事实之外,该工作正常。根据我所读到的,它不是那么可接受的方法,即它不安全,并且它会使页面变得严重等等(第二个是我最关心的)
所以它留给我一个会话。然而,会话不仅在回发之间持续存在,而且在它之后很久,即使用户离开页面也是如此。或者最糟糕的是 - 会话将在用户决定回发之前结束。因此,找到会话生命周期的最佳时间跨度是不可能的任务。
我的问题是在回发之间重用“数据集”的最佳做法是什么? 你们在这种情况下做了什么?
感谢。
PS:隐藏字段等不是一种选择。
答案 0 :(得分:3)
您可以在Cache中存储此类数据。它是应用程序范围的,因此根据您添加的内容,相应地使用密钥。
var key = UserID + "_personList";
Cache.Add(key, personList, null,
DateTime.Now.AddSeconds(60),
Cache.NoSlidingExpiration,
CacheItemPriority.High,
null);
请注意,您永远不能假设数据位于缓存中(可能已刷新),因此请务必检查它是否返回null并重新填充。
答案 1 :(得分:2)
Viewstate不是存储大型对象的好方法。正如您所提到的,您的页面大小会变得更大,每次回发都会占用大量时间。
我建议使用缓存。通过使用缓存,您的列表将不会保存到那里直到会话结束,您可以设置应该存储多长时间。对于缓存,您可以使用HttpCache或某些分布式缓存系统,如AppFabric或MemCached。 This nuget包将有助于使用这些缓存系统。
this链接将有助于如何配置AppFabric。
我应该使用一些代码进行编辑,以使其更有用。
https://bitbucket.org/glav/cacheadapter/wiki/Home
var cacheProvider = AppServices.Cache; // will pick cachadapter using web.config ( can be Http, Memory, AppFabric or MemCached)
var data1 = cacheProvider.Get<SomeData>("cache-key", DateTime.Now.AddSeconds(3), () =>
{
// This is the anonymous function which gets called if the data is not in the cache.
// This method is executed and whatever is returned, is added to the cache with the
// passed in expiry time.
Console.WriteLine("... => Adding data to the cache... 1st call");
var someData = new SomeData() { SomeText = "cache example1", SomeNumber = 1 };
return someData;
});
答案 2 :(得分:2)
除了缓存(Magnus的好主意)之外,我能想到的另一种方法是将繁重操作的结果保存在数据库服务器中。
您提到需要花费大量时间来检索数据。完成后,将其存储在具有某种类型访问密钥的特定建立表中。将该密钥提供给浏览器并使用它来提取您需要的部分。
当然,在不了解完整架构的情况下,提供解决方案真的很难。所以,按优先顺序排列:
在任何情况下我都不会将它存储在页面(视图状态),cookie(无论如何听起来太大)或会话中。
答案 3 :(得分:1)
您是否考虑过使用ASP.NET caching? 您应该选择一个能满足您确切需求的密钥,并将数据存储在服务器内存中。但请记住缓存是特定于应用程序的,并且对所有用户都有效 如果您处理的数据不经常更改,则处理算法不依赖于用户特定的设置,并且始终拥有最新数据并不重要,这可能是我能想到的最佳选择。
答案 4 :(得分:1)
将过滤后的集合存储在文件的磁盘上。为文件提供与您可以在viewstate中存储的密钥相同的名称。使用该密钥在回发时检索文件。为了防止文件系统填满,请有两个文件夹。替换保存文件的文件夹的日期。这样,您可以清除当天未使用的文件夹的内容。此方法具有极佳的性能,如果您的文件夹位置由网络路径标识,则可以使用Web场进行扩展。
答案 5 :(得分:0)
我认为personlist是一个共享对象。每个人都使用相同的列表吗?您可以存储在应用程序上。
Application["PersonList"] =persons;
persons = (List<"Person">)Application["PersonList"]
或者你可以存储在静态类中。
public static class PersonList { public static List<"Person"> Get {get;set;} }
您应该将此代码写入Global.asax文件
上的Application_StartPersonList.Get = ws.GetPersonsList();
您可以使用此代码获取List
persons = PersonList.Get;