2010-08-24 68 views
3

我有一個靜態變量的問題。我的控制器的組織部分如下:靜態變量問題

namespace MyApp.Controllers 
{ 
    public class DevicesController : Controller 
    {    
     static int some_var = 0;   

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult SetValue(int temp){ 
      some_var = temp; 
      return RedirectToAction("DisplayValue"); 
     } 

     [Authorize] 
     public ActionResult DisplayValue(){    
      .... 
      return View(some_object); 
     } 
    } 
} 

當多個用戶同時使用此視圖時,會出現問題。所有用戶使用相同的靜態變量並更改其值。如何解決此問題?

回答

7

可以使用,

HttpContext.Current.Session["some_var"] 

代替some_var,這將幫助。這將保留該記錄,一個會話的用戶,你可以用HttpContext.Current

namespace MyApp.Controllers 
{ 
    public class DevicesController : Controller 
    { 

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult SetValue(int temp){ 
      HttpContext.Current.Session["some_var"] = temp; 
      return RedirectToAction("DisplayValue"); 
     } 

     [Authorize] 
     public ActionResult DisplayValue(){ 

      .... 
      return View((int)HttpContext.Current.Session["some_var"]); 
     } 
    } 
} 
+0

在哪裏我可以找到任何示例工作與會話狀態的保存值 – Ognjen 2010-08-24 13:55:35

+0

我使用您的代碼時出現此錯誤: 'System.Web.HttpContextBase'沒有包含'當前'的定義和沒有擴展方法'當前'接受'System.Web.HttpContextBase'類型的第一個參數可以找到(你是否缺少使用指令或程序集引用?) – Ognjen 2010-08-24 14:07:24

+1

我建議不要使用HttpContext.Current.Session。只要使用Session,它就是ViewContext的一部分。使用HttpContext.Current通常不是一個好主意在MVC的土地:) – CubanX 2010-08-24 14:12:25

6

使其成爲私有實例變量,而不是靜態的。

如果你需要每個用戶維護這個計數(但只能用於指定會話),那麼你就可以做到以下幾點:

if (Session["Count"] == null) 
    Session["Count"] = 0; 
Session["Count"] = (int)Session["Count"] + MyNewValue; 

如果你想計數跨會話持續下去,那麼你能堅持它到一個數據庫。

+0

如果我把它設爲私人,那麼我會損失'some_var'的值。 – Ognjen 2010-08-24 13:03:57

+0

聽起來你想維護每個用戶的值*,所以它應該被保存到會話中,或者保存到具有相關用戶ID的數據庫中。 – RedFilter 2010-08-24 13:54:03

+0

在那裏我可以找到這個例子 – Ognjen 2010-08-24 14:02:35

1

靜態變量(和屬性)將在該類型的所有實例中共享 - 在本例中爲您的控制器。當應用程序池重新啓動時,該值將丟失。

如果您需要持續保存各個請求的值,對於特定用戶,則可能需要將其移至會話或類似位置。

如果您只需要在當前請求期間保留該值,那麼私有變量就足夠了。

+0

我需要在特定用戶的請求中持續存在的值,在會話中使用靜態變量的任何示例 – Ognjen 2010-08-24 13:07:08

+0

Ognjen:整個會話對象(HttpContext.Current.Session)是靜態的。請參閱Akash的迴應或查看如何在ASP.NET中使用會話。 :) – Teekin 2010-08-24 13:15:43

1

靜態訪問它有類變量和對象變量之間的重要區別。靜態變量是類變量,這意味着從一個類實例化的所有對象共享相同的變量,因此對象中該靜態變量的變化也會更改同一類的其他對象。 但是爲每個實例化對象創建一個非靜態變量(對象變量),所以更改不會影響其他實例。

但問題不在於選擇這兩者,因爲您的需求不同。您需要爲每個用戶保留一個變量。正如其他人所說,你必須使用會話變量。

但我認爲你應該閱讀關於對象變量和類變量。

+0

+1:理解任何編程任務的重要區別。 – RedFilter 2010-08-24 15:26:04

8

您的整個 ASP.NET MVC應用程序在AppDomain內運行,這是應用程序加上所有請求正在爲所有用戶服務,一切!

當您創建一個靜態變量時,會聲明一個實例並將其提供給整個AppDomain,每個用戶的每個請求都會看到相同的值。

一個實例變量(簡單地刪除'靜態'字)是特定於它所在的特定對象的一個​​實例。在這種情況下,該對象是您的Controller實例,因此您的變量作爲實例變量將是單獨的/只針對該控制器對象。 ASP.NET運行時將爲其所服務的每個請求創建一個Controller實例,然後在處理請求後丟棄該控制器對象。因此,如果您刪除靜態字詞,該變量將只在該請求的持續時間內保留,然後消失。

正如其他海報所說,您需要的是會話狀態。會話狀態持續會話的持續時間,就像在瀏覽您的網站的用戶中一樣,並且特定於每個用戶。因此,如果您將該變量存儲在會話狀態中,則每個用戶都會有所不同。

問題是當用戶離開你的網站時會話狀態消失,所以如果你需要它留在更長的時間,那麼你應該使用類似數據庫的東西。


從您的意見和原來的職位,它的聲音(我會嘗試儘可能禮貌把這個作爲可能的),你還沒有完全掌握了一些面向對象的編程風格和概念。雖然會話狀態本身不是OOP概念,但靜態變量和實例變量之間的區別是。我會建議刷新這些,作爲對這些概念的理解(面向對象編程)意味着,恕我直言,你甚至不會問這個問題。我希望這個答案有助於你的理解。

0

靜力學既不好也不壞。他們只是有不同的使用結構。 請考慮您正在處理國際電話號碼。 爲了做到這一點,您至少需要一個country_code,國家和唯一的ID。您可能還需要IDD國家/地區轉義前綴。 因此,您創建一個對象來保存所有這些,然後將它們從數據庫或其他方法收集到列表中。 您希望下拉列表中列出用戶選擇的國家,然後您希望country_code與您收集的任何內容一致。 如果您將國家/地區對象列表創建爲靜態,那麼當您進行往返服務器往返時,您無需每次都從其後備存儲庫重新加載列表,只需使用它填充下拉列表。由於這些數據永遠不會改變,因此可以將其設置爲靜態。網站上的每個人都將使用相同的國家列表,因此擁有一份副本並不重要。但是,您必須使ID用於非靜態列表索引,以便在列表中恢復選擇時,每個人都有自己的選擇,而不是全局靜態的,它顯示最後一個人選擇的內容。 將您的模型設置爲非靜態的county_code_id以使用列表中選定的ID,然後當您準備好更新數據時,請使用模型country_code_id查找country對象列表中的country_code,以返回country_code以供更新。

就像我說過的,靜力學既不好也不壞,它們只是有不同的用法。