2013-10-02 13 views
8

Ho due classi del modello:operazione di inserimento con molti-a-molti con 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; } 
} 

nome mio DbContext è JobsContext.

Il codice di sopra di me genera 3 tavoli candidati, Jobs & CandidatesJobs (generati automaticamente da EF)

Ora ho i record nella tabella di Lavoro: ID = 1, NAME = "Vendite": Id = 2, Name = "Ingegnere".

Desidero associare un nuovo Candidato che inserirò nella tabella Candidati con i 2 record della tabella Lavoro.

Prima di inserire il candidato conosco l'Id della tabella dei lavori & Non desidero effettuare una chiamata al database per ottenere maggiori dettagli dalla tabella dei lavori.

Come faccio a utilizzare Entity Framework 5?

risposta

17

Che ne dici di questo?

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(); 

Questo funziona solo se si è già andato a prendere i lavori dal database all'interno della stessa istanza del DbContext, altrimenti EF penseranno che i posti di lavoro sono 'nuovi' e cerca di inserirli. Se avete solo gli ID, si può provare il seguente:

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

Nel secondo blocco di codice, aggiungerà effettivamente nuovi record. – cbeckner

+0

@cbeckner che ne dici se chiami 'context.Jobs.Attach (nuovo Job {Id = salesJobId});' prima? –

+0

Questo lo farebbe. – cbeckner

6

Ci sono due opzioni.

Se si desidera disporre dello stesso contesto e degli oggetti candidati, è possibile semplicemente aggiungere gli oggetti candidati esistenti al lavoro. Per esempio: Create i vostri candidati e salvarli nel database:

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(); 

Quindi, creare il vostro lavoro:

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

Infine, aggiungere i vostri candidati per il nuovo job variabili, aggiungere il lavoro il contesto e salva le modifiche.

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

O

Se si utilizza un contesto diverso da quello creato i candidati con, quindi è possibile creare un nuovo oggetto candidato e collegarlo al contesto prima di aggiungere al lavoro.

//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); 

creare il nostro oggetto candidato impostando solo l'ID

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

Fissare l'oggetto al nuovo contesto. Nota: se il contesto dell'esempio precedente è ancora in giro, non ti consente di farlo poiché sta già monitorando il candidato.

newContext.Candidates.Attach(existingCandidate3); 

impostare lo stato di Invariato dal momento che non vogliamo creare un nuovo candidato, basta usare quello esistente.

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

Aggiungere e salvare le modifiche.

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

Fatto!

+0

Nella prima opzione l'effettuazione di 2 chiamate al database 1) per inserire il candidato 2) associare il candidato al lavoro. ** Stavo saltando per farlo su uno stesso INSERT **, come JobsContext.candidates.Add (candidato) che contiene un lavoro esistente. Fare riferimento a: [collegamento] (http://nileshhirapra.blogspot.in/2012/03/entity-framework-insert-operation-with.html) –

+0

È possibile rimuovere la chiamata 'SaveChanges' dopo aver creato i candidati nel primo esempio e effettua una chiamata a 'SaveChanges' dopo aver creato sia i candidati che il lavoro. Tuttavia, EF lo tradurrà ancora in numerose chiamate al database distinte (almeno * una per ogni tabella). La tua domanda ha fatto sembrare che volevi evitare un 'SELECT' contro la tabella dei candidati prima di aggiungerli al lavoro. – cbeckner

+1

Ho infastidito il codice per correggere il cambiamento di stato, mancava il 'Entity' nel tuo codice: il corretto è System.Data.Entity.EntityState.Unchanged –

0

Una soluzione molto semplice è quella di creare una vista della tabella di riferimento esterno esattamente come la tabella (view_tablename_raw). Quindi aggiorna quella vista in EF come entità senza chiavi esterne. Dal loro uso contesto .view_tablename_raw.Add (...) e funzionerà perfettamente.

Problemi correlati