2012-01-17 83 views
3

我在这里发现了很多关于在viewstate中存储值的问题,但还没有找到一个好的答案。会话而不是意见

我有一种情况,当我从数据库检索大量的数据。然后我根据自己的需要筛选和处理数据(所以这是一个非常重要的过程)。然后我把结果放在自定义类的列表中。例如让我们说这个类将是人

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类标记为serializeable,并将列表存储在viewstate中,除了由于视图状态而导致页面变为1mb大小这一事实以外,它工作正常。根据我所读到的,这是不可接受的方法,即它是不安全的,它吹的源代码使页面沉重等(第二个是我最关心的)

因此,它留给我一个会议。然而,会话不仅在回发之间持续存在,甚至在用户离开页面之后也会持续很久。或者最糟糕的是,会话将在用户决定回发之前结束。因此,找到会话寿命的最佳时间跨度是不可能的。

我的问题是在回发之间重复使用“数据集”的最佳做法是什么? 你们在这种情况下做什么?

谢谢。

PS:隐藏字段等不是一个选项。

+0

获取列表这个人列表应用宽或过滤上当前登录的用户? – Magnus 2012-01-17 22:05:36

+0

在您第一次检索它之后,您可以将它保存在其他地方吗?已过滤的数据集?如果是这样,您可以将它与一个唯一的密钥一起存储并仅将密钥发送给客户端。 – GemCer 2012-01-17 22:08:07

+0

如何存储缓存数据的临时数据库表? – Holystream 2012-01-17 22:09:35

回答

3

您可以将此类数据存储在Cache中。它是广泛的应用程序,因此根据您添加的内容使用相应的密钥。

var key = UserID + "_personList"; 
Cache.Add(key, personList, null, 
    DateTime.Now.AddSeconds(60), 
    Cache.NoSlidingExpiration, 
    CacheItemPriority.High, 
    null); 

请注意,你不能假设数据是在缓存中(它可能已经被刷新),所以经常检查,如果返回null,比填充它。

+0

我同意。如果在数据库中进行所有过滤(这就是它的作用)是不允许的,那么缓存数据将是最好的选择。 ViewState和Session不应该被滥用。 – NotMe 2012-01-17 22:11:15

+0

'Cache'将有利于不会被隐藏在隐藏区域(“__VIEWSTATE”)内,而是在服务器上... – 2012-01-17 22:15:28

+0

那么缓存在会话中的优势是什么? – jekcom 2012-01-17 22:27:01

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; 
}); 
+0

有趣的我会看看这个。谢谢 – jekcom 2012-01-17 22:28:01

1

你有没有考虑过使用ASP.NET caching
您应该选择一个能满足您确切需求的密钥,并将您的数据存储在服务器内存中。但请记住,缓存是特定于应用程序的,并且适用于所有用户。
如果您处理的数据不经常更改,处理算法不取决于用户特定的设置,并且始终拥有最新数据并不重要,也许这是我能想到的最佳选择。

2

除了缓存(Magnus的一个好主意)之外,我能想到的唯一方法就是保留存储在数据库服务器中的繁重操作的结果。

您提到它需要大量的时间来检索数据。完成后,将其存储在一个特定的表格中,并带有某种类型的访问键。将该密钥提供给浏览器,并用它来拉出你需要的部分。

当然,如果不知道完整的架构,很难提供解决方案。因此,按照优先顺序:

  1. 将其存储在数据库中,并为该用户指定一个唯一的密钥。
  2. 储存于远程高速缓存
  3. 储存于本地缓存

在任何情况下,我会它存储在页面(视图状态),饼干(声音太大反正),或在会话。

+0

好主意,非规范化的数据读取模型。 “ – Magnus 2012-01-17 22:33:00

+0

”用此用户的唯一密钥将其存储在数据库中。“数据可能会频繁更改。数据的有效生命周期几乎就是用户停留在页面上的时间。而且我认为这种方式我们失去了灵活性,除非我们序列化列表并存储对象。但是,那么它会在每次我们需要它时反序列化服务器的性能吗? – jekcom 2012-01-17 22:33:57

+1

@jekcom:如果每次需要时都无法提取新数据,那么无论您在何处放置数据,您总是要处理陈旧的信息。这个问题真的归结为如何过时是可以接受的。如果没有,那么你绝对必须再次拉它。如果几分钟(他们将在页面上的时间),然后缓存它。在任何情况下你都不会使用会话。 – NotMe 2012-01-17 22:40:06

1

将过滤的集合存储在磁盘中的文件中。为该文件提供与您可以在视图状态下存储的密钥相同的名称。使用该键在回发中检索文件。为了防止文件系统被填满,有两个文件夹。替换文件夹保存文件的日期。这样,您可以清除当天没有使用的文件夹的内容。此方法具有非常出色的性能,并且如果您的文件夹位置由网络路径标识,则可以使用Web场进行扩展。

0

我认为personlist是一个共享对象。每个人都使用相同的列表吗?您可以在应用程序上存储。

Application["PersonList"] =persons; 

persons = (List<"Person">)Application["PersonList"] 

或者你也可以存储静态类。

public static class PersonList { public static List<"Person"> Get {get;set;} } 

你应该写这段代码的Application_Start在Global.asax文件

PersonList.Get = ws.GetPersonsList(); 

,您可以通过使用此代码

persons = PersonList.Get;