2011-08-22 45 views
1

我最近與實體框架開始的MVC項目我做得到與技術的夾具和我有幾個問題:..實體框架 - 建議和最佳實踐

我第一個是這個,這是我的一個實體保存代碼 - 這是最好的方式..它看起來有點涉嫌我..

public bool SavePrank(PrankDefinition prank) 
    { 

     if (prank == null) 
      throw new ArgumentNullException("prank"); 

     if (prank.ID == 0) 
     { 
      DataBase.Pranks.Add(prank); 
      DataBase.SaveChanges(); 
     } 
     else 
     { 
      DataBase.Pranks.Attach(prank); 
      DataBase.Entry(prank).State = EntityState.Modified; 
      DataBase.SaveChanges(); 
     } 

     return true; 

    } 

香港專業教育學院還得到這個代碼,獲取最新版本的實體..

public List<PrankDefinition> GetPranks() 
    { 
     List<PrankDefinition> pranks = DataBase.Pranks.Where(p => p != null).ToList(); 

     foreach (PrankDefinition prankDef in pranks) 
     { 
      DataBase.Entry(prankDef).Reload(); 
     } 

     return pranks; 
    } 

iive不得不調用實體的重新加載的原因是因爲當另一個客戶端正在使用該項目時 - 實體的更改不會立即反映出來(這很關鍵)。我的問題是 - 有沒有更好的方法來做到這一點?有什麼我可以附加到Where方法來獲取最新版本?

我的上下文 - 如果它可以幫助..

public static DataContext DataBase 
    { 
     get 
     { 
      if (HttpContext.Current != null &&   HttpContext.Current.Session["DataBase"]== null) 
      { 
       HttpContext.Current.Session["DataBase"] = new DataContext(); 
      } 

      return HttpContext.Current.Session["DataBase"] as DataContext; 
     } 
     set 
     { 
      if (HttpContext.Current != null) 
       HttpContext.Current.Session["DataBase"] = value; 
     } 
    } 

任何幫助將是非常美妙!

編輯:更新到數據文本

這會是一個更好的實施的DataContext的?

public static DataContext DataBase 
    { 
     get { return new DataContext(); } 
    } 

歡呼聲。 ste。

回答

4

只是幾句話:

  • 在我看來SaveChanges完成的工作單位,不屬於單個存儲庫的方法,如SavePrank。我可能更喜歡這樣的模式:

    InsertOrUpdatePrank(prank); // = SavePrank without SaveChanges 
    ModifyPerhapsSomeOtherEntity(otherEntity); 
    SetPerhapsRelationshipBetweenPrankAndOtherEntity(prank, otherEntity); 
    // ... more ... 
    DataBase.SaveChanges(); 
    

    這樣,所有更改都寫入到單個事務中的數據庫。

  • 你在哪裏處置你的上下文?如果您實例化並將其存儲在會話中,但不要在代碼中明確地處理上下文,則該上下文將存在於多個請求中。這是一個大問題的潛在根源,因爲當您處理新的請求時,您的上下文可能仍包含來自舊請求的實體。例如:如果prankID = 123在來自同一用戶的兩個後續請求(在同一會話中)中更新兩次DataBase.Pranks.Attach(prank)將引發異常,因爲來自先前具有相同ID的請求的舊惡作劇已被附加到上下文。在Web應用程序中,上下文永遠不應該比單個請求活得更長,以避免出現像以上這樣的問題。

  • 如果您爲每個請求處理上下文,我不再需要「重新加載」實體。無論如何,您必須從數據庫加載實體,因爲每個上下文都是新的,並且在您輸入操作時爲空。所以,沒有什麼可以重新加載。無論如何,當你運行你的查詢時,你會從數據庫中獲得最新版本的實體。

  • Where(p => p != null)是沒有意義的。要獲取所有行,你可以這樣寫:

    List<PrankDefinition> pranks = DataBase.Pranks.ToList(); 
    
+0

感謝所有隊友的建議。 SavePrank方法是非常自包含的,所以這就是爲什麼我在那時使用SaveChanges - 這仍然是不正確的?..另請參閱更新上下文。 – Steoates

+0

@Stephen:不,在這種特殊情況下並不正確。這就是如何在更復雜的情況下處理SaveChanges的問題。在我看來,將SaveChanges保存在存儲庫之外是更好的方法。您在問題中的更新很糟糕:您每次訪問「數據庫」屬性時都會創建一個新的上下文。 – Slauma