2012-09-28 110 views
1

其實我花了整天的時間在外鍵的EntityFramework上。 假設我們有兩個表。 過程(APP_ID,PROCESS_ID) LookupProcessId(PROCESS_ID,process_description)使用數據庫外鍵的EntityFramework

你能理解其名稱,第一個表兩張表,使用PROCESS_ID指示每一個應用程序,並說明是在seoncd表。 其實我嘗試了很多次,弄清楚如何inquery做:感覺有點像

Dim result = (from x in db.Processes where x.LookupProcess is (from m in db.LookupProcessIds where descr = "example" select m).FirstOrDefault() select x).FirstOrDefault() 

首先我想問的是有更簡單的方法來做到這一點。

其次我要問的問題是關於插入

p As New AmpApplication.CUEngData.Process 
    p.app_id=100 
    p.LookupProcess = (from m in db.LookupProcessIds where descr = "example" select m).FirstOrDefault() 
db.AddToProcesses(p) 
db.SaveChanges() 

從外觀上看起來很好,但它給我的錯誤說 實體在「AmpCUEngEntities.Processes」參加「FK_Process_LookupProcess」的關係。找到0個相關的「LookupProcess」。預計會有'LookupProcess'。

我可以問的是,插入錯誤?這是我的查詢是否正確?

+0

對於第二部分,實際上是否存在LookupProcess返回的實例? – jeroenh

+0

實例返回是什麼意思? – Hypnoz

+0

數據庫中是否有實際記錄? – jeroenh

回答

0

關於第一個問題:

Dim result = (from x in db.Processes 
       where x.LookupProcess.descr = "example" 
       select x).FirstOrDefault() 
+0

實際上,我之前試過這個,它表示空指針....是EF版本的問題? – Hypnoz

+0

,如果它的工作,我可以做的事情,如p.LookupProcess.descr =「example」作爲插入 – Hypnoz

0

實際上,你從DataEntityModel,其框架錯過了一些概念。爲了處理數據,你必須從上下文的角度來調用對象。這些允許您指定ObjectStateManager DataObject的狀態。在你的情況下,如果你有依賴於FK的數據,你將不得不添加/更新從葉到根的任何鏈接數據。

這個例子演示了簡單的(不依賴)數據操作。選擇是否存在以及插入或更新。

如果您想了解ObjectStateManager操作的詳細信息請訪問http://msdn.microsoft.com/en-us/library/bb156104.aspx

Dim context As New Processing_context 'deseign your context (this one is linked to a DB) 

    Dim pro = (From r In context.PROCESS 
        Where r.LOOKUPPROCESS.descr = LookupProcess.descr 
        Select r).FirstOrDefault() 

    If pro Is Nothing Then 'add a new one 
     pro = New context.PROCESS With {.AP_ID = "id", .PROCESS_ID = "p_id"} 

     context.PROCESS.Attach(pro) 
     context.ObjectStateManager.ChangeObjectState(pro, System.Data.EntityState.Added) 
    Else 
     'update data attibutes 
     pro.AP_ID = "id" 
     pro.PROCESS_ID = "p_id" 

     context.ObjectStateManager.ChangeObjectState(pro, System.Data.EntityState.Modified) 
     'context.PROCESS.Attach(pro) 
    End If 

    context.SaveChanges() 

我希望這將有助於。祝你今天愉快!

+0

的方式不能只是添加,而不是附加和更改狀態添加? – Pawel

+0

不建議使用引用或其他任何操作數據。 – Minus

+0

Attach假定實體已經在數據庫中。此外,如果您將狀態更改爲已添加,我相信EF不會看到任何區別。顯然,如果你知道密鑰和數據庫生成密鑰,你想使用Attach,但如果你自己設置密鑰,那麼我相信Add是正確的。就相關實體而言 - Attach和Add都不是理想的。附加將附加實體和所有相關實體(因此它會假定它們都在數據庫中),而添加將添加實體和所有相關實體(因此它會假定它們都不在數據庫中) – Pawel

0

關於第一個問題,以擴大建議什麼@jeroenh:

Dim result = (from x in db.Processes.Include("LookupProcess") 
    where x.LookupProcess.descr = "example" 
    select x).FirstOrDefault() 

加入了Include語句將滋潤LookupProcess實體,這樣就可以對它們進行查詢。如果沒有Includex.LookupProcess將爲空,這可能會解釋爲什麼你得到了錯誤。

如果使用文字字符串作爲參數Include不理想,請參閱Returning from a DbSet 3 tables without the error "cannot be inferred from the query"以獲取使用嵌套實體的示例。

關於第二個問題,這條線

p.LookupProcess = (from m in db.LookupProcessIds 
    where descr = "example" select m).FirstOrDefault() 

可能以後會造成問題,因爲如果沒有LookupProcessId與「榜樣」的process_description,你會得到null。從MSDN

引用和可爲空的類型的默認值爲null。

正因爲如此,如果p.LookupProcess當您插入實體爲空,你會得到異常:

實體在「AmpCUEngEntities.Processes」參加「FK_Process_LookupProcess」的關係。找到0個相關的「LookupProcess」。預計會有'LookupProcess'。

爲避免此類問題,您需要檢查p.LookupProcess在進入數據庫之前是否爲空。

If Not p.LookupProcess Is Nothing Then 
    db.AddToProcesses(p)   
    db.SaveChanges()   
End If