会话而不是viewstate

时间:2012-01-17 22:02:18

标签: c# asp.net

我在这里发现了许多关于在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:隐藏字段等不是一种选择。

6 个答案:

答案 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或某些分布式缓存系统,如AppFabricMemCachedThis 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的好主意)之外,我能想到的另一种方法是将繁重操作的结果保存在数据库服务器中。

您提到需要花费大量时间来检索数据。完成后,将其存储在具有某种类型访问密钥的特定建立表中。将该密钥提供给浏览器并使用它来提取您需要的部分。

当然,在不了解完整架构的情况下,提供解决方案真的很难。所以,按优先顺序排列:

  1. 使用此用户的唯一键将其存储在数据库中。
  2. 将其存储在远程缓存中
  3. 将其存储在本地缓存中
  4. 在任何情况下我都不会将它存储在页面(视图状态),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_Start
PersonList.Get = ws.GetPersonsList();

您可以使用此代码获取List

persons = PersonList.Get;