2013-01-13 24 views
7

我想在斷開(從上下文)模式下使用實體框架POCO。在我的場景中,我創建了一個新的Parent對象,並希望將現有的子對象附加到它,然後將其保存到數據庫。
下面的代碼會在保存新學生記錄時插入新課程記錄,而不希望將現有課程記錄鏈接到新學生記錄。實體框架:將現有的子POCO添加到新的父POCO,在DB中創建新的子節點

我怎樣才能在實體框架在那裏......

  • 的對象可以從上下文斷開做到這一點。 (即在一個上下文中查詢,然後保存在不同的上下文中)
  • 我不需要重新從數據庫中查詢子記錄,所以我可以在保存到數據庫時將它附加到父級。當我已經將它作爲內存中的一個對象時,我真的想要避免額外訪問數據庫。

此頁面顯示下面的代碼是基於http://entityframeworktutorial.net/EF4_EnvSetup.aspx#.UPMZ4m-UN9Y

class Program 
{ 
    static void Main(string[] args) 
    { 

     //get existing course from db as disconnected object 
     var course = Program.getCourse(); 

     //create new student 
     var stud = new Student(); 
     stud.StudentName = "bob"; 

     //assign existing course to the student 
     stud.Courses.Add(course); 

     //save student to db 
     using (SchoolDBEntities ctx = new SchoolDBEntities()) 
     { 
      ctx.Students.AddObject(stud); 
      ctx.SaveChanges(); 
     } 
    } 

    static Course getCourse() 
    { 
     Course returnCourse = null; 

     using (var ctx = new SchoolDBEntities()) 
     { 
      ctx.ContextOptions.LazyLoadingEnabled = false; 
      returnCourse = (from s in ctx.Courses 
          select s).SingleOrDefault(); 
     } 

     return returnCourse; 
    } 
} 

回答

17

我相信有很少的方法來完成這一點。 您可以指定過程的實體是不變的,而不是增加,沿着這些線路:

ctx.Entry(course).State = EntityState.Unchanged; 

或指示你的背景,你是與現有的實體工作:

ctx.Courses.Attach(course); 

此處瞭解詳情: http://msdn.microsoft.com/en-us/data/jj592676.aspx

編輯

我的解決方案中有一些正在運行的樣本,我證實它們按預期工作。 在所有情況下,我們在ID = 2和Name =「Addison Wesley」的數據庫中都有發佈商記錄(與示例無關,但僅用於良好衡量)。

方法1 - 設置實體狀態

using (var context = new Context()) 
{ 
    var book = new Book(); 
    book.Name = "Service Design Patterns"; 
    book.Publisher = new Publisher() {Id = 2 }; // Only ID is required 
    context.Entry(book.Publisher).State = EntityState.Unchanged; 
    context.Books.Add(book); 
    context.SaveChanges(); 
} 

方法2 - 使用Attach方法

using (var context = new Context()) 
{ 
    var book = new Book(); 
    book.Name = "Service Design Patterns";     
    book.Publisher = new Publisher() { Id = 2 }; // Only ID is required 
    context.Publishers.Attach(book.Publisher); 
    context.Books.Add(book); 
    context.SaveChanges(); 
} 

方法3 - 設置外鍵值

using (var context = new Context()) 
{ 
    var book = new Book(); 
    book.Name = "Service Design Patterns"; 
    book.PublisherId = 2; 
    context.Books.Add(book); 
    context.SaveChanges(); 
} 

對於這最後的方法來工作,我需要添加額外的屬性的publisherId,它被命名爲根據NavigationPropertyName +「ID」約定由EF auotmatically被拾起:我在這裏使用EF5代碼

public int PublisherId { get; set; } 
public Publisher Publisher { get; set; } 

首先,它與POCO非常相似。

+0

第二個選項幾乎可行,但我得到一個「該對象無法連接,因爲它已經在對象上下文中。」 「ctx.Students.AddObject(stud)」錯誤;「線。我假設在做「stud.Courses.Add(course)」的時候,我無法做到這一點;「在它之前。我想仍然在柱頭物體中使用課程系列。 – MakkyNZ

+0

那麼,我沒有一個方便測試的解決方案,但是先嚐試附加它,然後將其添加到學生。希望這種方式不會被EF標記爲「已添加」。 –

+0

這不是很理想。我希望首先在對象級別發生父 - >子關係,因爲它可能尚未準備好保存到數據庫。也許我應該刪除EF生成的實體之間的所有關係,並手動控制它自己? – MakkyNZ

0

實體框架不允許跨語境的關係數據庫圖表。

如果您在同一使用語句中放置課程的閱讀並將課程連接到學生,它將起作用。

0

我也嘗試了第二個選項,它爲我工作。我確實喜歡首先在對象級別發生父 - >子關係並保存到數據庫。也許我應該刪除EF生成的實體之間的所有關係,並自己手動控制這些關係。