2012-07-25 113 views
3

我有以下EF代碼第一個代碼。它工作正常。但是,當我查看'club2.Members'的價值時,它會顯示以下內容:類型'System.ObjectDisposedException'的異常

'club2.Members'拋出了'System.ObjectDisposedException'類型的異常。

消息是:

的ObjectContext的實例已被設置,並且不再能夠用於需要連接的操作。

我沒有爲會員屬性設置值。沒關係。但是它不應該在內部造成任何異常。

  1. 有沒有辦法克服這個異常?
  2. 刪除此異常是否有助於提高性能?
  3. 爲什麼這個異常不會導致程序執行終止?

注意:我不需要俱樂部實體中的會員數據(在我打電話的地方)。即使當時沒有成員加入俱樂部。我需要的是擺脫例外;不要使用熱切加載來加載數據。如何避免異常

enter image description here

namespace LijosEF 
{ 

public class Person 
{ 
    public int PersonId { get; set; } 
    public string PersonName { get; set; } 
    public virtual ICollection<Club> Clubs { get; set; } 
} 

public class Club 
{ 
    public int ClubId { get; set; } 
    public string ClubName { get; set; } 
    public virtual ICollection<Person> Members { get; set; } 

} 




//System.Data.Entity.DbContext is from EntityFramework.dll 
public class NerdDinners : System.Data.Entity.DbContext 
{ 

    public NerdDinners(string connString): base(connString) 
    { 

    } 

    protected override void OnModelCreating(DbModelBuilder modelbuilder) 
    { 
     //Fluent API - Plural Removal 
     modelbuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
    } 

    public DbSet<Person> Persons { get; set; } 
    public DbSet<Club> Clubs { get; set; } 



} 
} 




    static void Main(string[] args) 
    { 
     Database.SetInitializer<NerdDinners>(new MyInitializer()); 

     CreateClubs(); 
     CreatePersons(); 

    } 

    public static void CreateClubs() 
    { 

     string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
     using (var db = new NerdDinners(connectionstring)) 
     { 

      Club club1 = new Club(); 
      club1.ClubName = "club1"; 

      Club club2 = new Club(); 
      club2.ClubName = "club2"; 

      Club club3 = new Club(); 
      club3.ClubName = "club3"; 

      db.Clubs.Add(club1); 
      db.Clubs.Add(club2); 
      db.Clubs.Add(club3); 

      int recordsAffected = db.SaveChanges(); 


     } 
    } 

    public static Club GetClubs(string clubName) 
    { 
     string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
     using (var db = new NerdDinners(connectionstring)) 
     { 

      var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName); 
      return query; 
     } 
    } 

    public static void CreatePersons() 
    { 
     string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
     using (var db = new NerdDinners(connectionstring)) 
     { 

      Club club1 = GetClubs("club1"); 
      Club club2 = GetClubs("club2"); 
      Club club3 = GetClubs("club3"); 

      //More code to be added (using db) to add person to context and save 
     } 
    } 
+0

我剛剛忽略了你的代碼。爲什麼在CheckValues中創建另一個數據庫實例? – 2012-07-26 07:35:50

+0

@AmiramKorach我有另一種方法 - CreatePersons。我將不得不在那裏使用新的環境。我正在使用Context Per Request方法。人們需要了解俱樂部。 – Lijo 2012-07-26 08:05:27

+0

這段代碼沒有意義。您在CreatePersons中根本不使用數據庫變量。每個GetClubs調用都使用自己的數據庫變量。 – 2012-07-26 08:12:33

回答

0

方法1

沒有必要對下面的方法。這可以在目前的情況下完成。這只是一個選擇。

GetClubs("club1"); 

方法2

附加實體解決了這個問題:

  Club club1 = GetClubs("club1"); 
      Club club2 = GetClubs("club2"); 
      Club club3 = GetClubs("club3"); 

      ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)club1); 
      ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)club2); 
      ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)club3); 


      var test = club2.Members; 

我不應該試圖引用(俱樂部級)club2.Members,因爲它不需要用於創建Person對象。

成員是Club類中的相關數據。由於它是虛擬的,它會執行延遲加載。

在另一種情況下,如果我必須從不同的上下文中檢索成員對象(這是一個相關的數據),我應該依靠急切的加載(在爲您提供Club對象的地方)。

也請參閱以下內容:

  1. Entity Framework: Duplicate Records in Many-to-Many relationship

  2. System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

  3. The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

  4. ObjectContext instance has been disposed while binding

+0

@AmiramKorach你對這種方法有什麼看法? – Lijo 2012-07-26 06:34:40

+1

堅持Amiram的建議。這僅適用於您將實體重新附加到新的上下文。我認爲在你的情況下,你想使用Include來進行急切的加載。每次你想訪問導航屬性時打開新的上下文不是一個好主意。請記住,因爲您將導航屬性標記爲虛擬,因此EF將返回動態代理,該代理在處理上下文時不起作用。在關閉上下文之前返回所需的所有數據將解決問題。 – JaySilk84 2012-07-26 07:29:20

+0

我覺得這很危險。正如我上面所說的,我不認爲有必要在CheckValues中打開一個新的上下文。此外,我不會嘗試將實體附加到多個上下文。我不確定你不會爲此得到例外。 – 2012-07-26 07:38:35

7

,因爲你要丟棄的的DbContext執行查詢後,您會收到此錯誤。如果你想使用「成員」中的數據,然後加載與查詢: http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

如果你不需要延遲加載,這意味着只有你在查詢加載的數據加載(這將消除異常),設置LazyLoadingEnabled = false。看看這裏: Disable lazy loading by default in Entity Framework 4

+0

我不需要在俱樂部實體的會員數據(以我稱之爲的點)。即使在那個時候,也沒有會員加入俱樂部。我需要的是擺脫例外;不加載數據。如何避免異常? – Lijo 2012-07-25 14:39:41

+0

剛剛編輯我的答案 – 2012-07-26 03:23:55

相關問題