2013-10-02 74 views
8

插入操作我有兩個示範類:許多一對多的關係,使用EF

public class Candidate 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public ICollection<Job> Jobs { get; set; } 
} 

public class Job 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public ICollection<Candidate> Candidates { get; set; } 
} 

我的DbContext的名字是JobsContext。

上面的代碼生成了我3分表的考生,喬布斯& CandidatesJobs(由EF自動生成)

現在我已經在職位表中的記錄:ID = 1,名稱= 「銷售」:ID = 2,名稱= 「工程師」。

我想關聯一個新的Candidate,我將在Jobs表中插入Candidates表和2條記錄。

插入候選人之前我知道作業表的ID's &我不想調用數據庫以從作業表中獲取更多詳細信息。

如何使用實體框架5來做到這一點?

回答

17

這個怎麼樣?

Job salesJob; // already fetched from db 
Job engineerJob; // already fetched from db 

Candidate candidate = new Candidate(); 
candidate.Name = "John Doe"; 
candidate.Jobs = new List<Job>(); // you could also do this in the constructor of Candidate 
candidate.Jobs.Add(salesJob); 
candidate.Jobs.Add(engineerJob); 

context.SaveChanges(); 

這隻能如果您已經是DbContext的同一實例中獲取來自數據庫的工作,否則將EF認爲工作是「新」,並試圖將其插入。如果你只有IDS,你可以嘗試以下方法:

var salesJob = new Job { Id = salesJobId }; 
var engineerJob = new Job { Id = engineerJobId }; 

context.Jobs.Attach(salesJob); 
context.Jobs.Attach(engineerJob); 

candiate.Jobs.Add(salesJob); 
candiate.Jobs.Add(engineerJob); 
context.SaveChanges(); 
+0

在第二個代碼塊中,它實際上會添加新記錄。 – cbeckner

+0

@cbeckner如果你調用'context.Jobs.Attach(new Job {Id = salesJobId});'first? –

+0

這會做到這一點。 – cbeckner

6

有兩種選擇。

如果您將要放置相同的上下文和候選對象,可以簡單地將現有的候選對象添加到作業中。 例如: 創建您的候選人,並將其保存到數據庫中:

JobsContext context = new JobsContext(); 
var candidate1 = new Candidate() { Name = "John Smith" }; //id 1 
var candidate2 = new Candidate() { Name = "Jane Smith" }; //id 2 
var candidate3 = new Candidate() { Name = "John Doe" }; //id 3 
context.Candidates.Add(candidate1); 
context.Candidates.Add(candidate2); 
context.Candidates.Add(candidate3); 
context.SaveChanges(); 

然後,創建你的工作:

var job = new Job() { Name = "Good Job" }; //id 1 

最後,您的考生加入到新job變量,就業增加上下文並保存更改。

job.Candidates.Add(candidate1); 
job.Candidates.Add(candidate2); 
context.Jobs.Add(job); 
context.SaveChanges(); 

OR

如果使用的是從你創建的候選人一個不同的環境,那麼你可以創建一個新的候選對象,並在它之前增加了其附加到上下文工作。

//different context from above example 
JobsContext newContext = new JobsContext(); 
//this can be a new or existing job, using the job from the example above here 
var existingJob = newContext.Jobs.FirstOrDefault(j => j.Id == 1); 

通過設置的ID

var existingCandidate3 = new Candidate() { Id = 3 }; 

連接對象到新的環境中創建我們的候選對象。 注意:如果上述示例的上下文仍然存在,它不會讓您這樣做,因爲它已經在跟蹤候選人了。

newContext.Candidates.Attach(existingCandidate3); 

設置狀態不變,因爲我們不希望創建一個新的候選人,只是利用現有的一個。

newContext.Entry(existingCandidate3).State = System.Data.EntityState.Unchanged; 

添加並保存更改。

existingJob.Candidates.Add(existingCandidate3); 
newContext.SaveChanges(); 

完成!

+0

在第一個選項中,您將進行2個數據庫調用1)插入候選人2)將候選人與作業相關聯。 **我正在跳轉到一個INSERT本身**上,如JobsContext.candidates.Add(候選),其中包含一個現有的工作。請參閱:[鏈接](http://nileshhirapra.blogspot.in/2012/03/entity-framework-insert-operation-with.html) –

+0

在第一個示例中創建候選項後,可以刪除SaveChanges調用,在創建候選人和作業後,打一次電話給'SaveChanges'。但是,EF仍然會將其轉換爲幾個不同的數據庫調用(每個表至少*一個)。你的問題聽起來就像你想在候選人表中添加「SELECT」,然後將他們添加到工作中。 – cbeckner

+1

我修改了代碼來糾正狀態變化,在你的代碼中缺少'Entity':正確的是System.Data.Entity.EntityState.Unchanged –

0

一個非常簡單的解決方案是創建外部參照表的圖完全一樣的表(view_tablename_raw)。然後在EF中將該視圖更新爲沒有外鍵的實體。從他們的使用上下文 .view_tablename_raw.Add(...),它將無縫工作。