2011-08-20 103 views
0

如何使用僅導航屬性集合創建+ persist + have-a-proxy-代碼優先的poco的新實例?在下面的代碼中,如果使用成員函數創建POCO,然後創建POCO,我將展示如何執行此操作。您沒有DbContext,但是如果您創建一個對象並使用DbSet.Add保存它,則返回的對象不是代理,因此您無法反過來使用其DbSet.Add來添加不同的子對象。EF代碼首先,使用代理創建新對象集合

在此代碼中,如果您調用MailingList.AddIncomingMessage(「my message」),則會在「OOPS」註釋中收到異常,因爲創建的消息不是代理,因此其Message.doodads屬性爲null 。

class Doodad { 
    public int ID { get; set; } 
    public string doodad { get; set; }; 
} 

class Message { 
    public int ID { get; set; } 
    public virtual MailingList mailingList { get; set; } 
    public virtual ICollection<Doodad> doodads { get; set; } 
    public string text { get; set; } 

    public void GetDoodadCreateIfNeeded(string doodad) { 
    try { 
     // won't be found since we just created this Message 
     return this.doodads.First(d => d.doodad == doodad); 
    } catch (Exception e) { 
     Doodad newDoodad = new Doodad() { doodad=doodad }; 

     // OOPS! this.doodads == null, because its not a proxy object 
     this.doodads.Add(newDoodad); 
     return newDoodad; 
    } 
    } 
} 

class MailingList { 
    public int ID { get; set; } 
    public virtual ICollection<Message> messages { get; set; } 

    public void AddIncomingMessage(string message) { 
    var msg = new Message() { text=message }; 

    // we have no Context, because we're in a POCO's member function 
    this.messages.Add(msg); 

    var doodad = msg.GetDoodadCreateIfNeeded("bongo drums"); 
    } 
} 

編輯:對不起你們,我忘了把屬性訪問器和ID在該簡化的情況,但我在實際的代碼中使用它們。

+0

給任何人遇到了這種正確的方式,檢查出http://stackoverflow.com/ Alex的評論問題/ 5974448/entityframework-4-1-dbcontext-changetracking-kill-performance – Seth

回答

2

它與代理無關。它和任何其他代碼一樣 - 如果你想使用對象/集合,你必須首先初始化它!你的拳頭命令:

return this.doodads.First(d => d.doodad == doodad); 

不會拋出異常,因爲它沒有發現doodad但由於doodads爲空。

你需要做什麼?您需要在首次使用前初始化集合。你可以這樣做:

  • 直接在他們的定義
  • 在實體的構造
  • 在屬性getter(延遲初始化),一旦他們首先需要 - 這將需要改變你的領域是BTW性能。寫在.NET
  • 在您的自定義方法的類,你可以檢查它們是否爲空,並初始化它們
+0

我一直關心添加構造函數,因爲我不想覆蓋數據庫中的數據......例如如果我有:public Message(){this.doodads = new IList (); },如果已經存在關於裝飾的關聯,它會不小心覆蓋從數據庫加載的數據,還是隻會在數據加載之前調用它(或者只有在我明確執行新操作時調用它)? – Seth

+0

當我明確地初始化與上述構造函數的裝飾物,當我稍後嘗試context.SaveChanges()我得到:InvalidOperationException「集合被修改;枚舉操作可能不會執行。我想也許我需要一個代理? – Seth

+0

拉迪斯拉夫,你能舉一個初始化集合的例子嗎?我目前正在創建一個新的列表,並在我這樣做時發生錯誤。我應該使用與List不同的類型嗎? – Seth

1

與導航屬性相輔相成,您需要具有屬性即外鍵的Id。

所以,你的郵件列表,需要有此屬性:

[Key] // this attribute is important 
    public int Id { get; set; } 

,你將不得不更改消息CLASSE有這些屬性:

public virtual int mailingListId { get; set; 
public virtual MailingList mailingList { get; set; } 

{ get; set; }性能是很重要的,所以它是一種財產,而不僅僅是一種公共屬性。

+0

good catch Doug,我忘了在做簡化示例時嘗試更加明確地解釋我的問題。 – Seth