Insert operation with many-to-many relationship using EF

asp.net-mvc c# entity-framework many-to-many

Question

My two model classes are:

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; }
}

JobsContext is the name of my DbContext.

With the code above, I get three tables: Candidates, Jobs, and CandidatesJobs (autogenerated by EF)

I currently have the following records in the Jobs table: Id = 1, Name = "Sales"; Id = 2, Name = "Engineer."

I want to link the two records from the Jobs table to the new Candidate that I will create into the Candidates table.

I already know the IDs for the Jobs table before entering the Candidate, and I don't want to access the database to collect more information from the Jobs table.

In what way may Entity Framework 5 be used for this?

1
9
6/12/2014 2:13:46 PM

Accepted Answer

Let's try this.

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

This only functions if the jobs were already pulled from the database using the same instance of theDbContext if not, EF will attempt to insert them thinking they are "new" jobs. You might try the following if you only have the 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();
20
6/12/2014 1:59:33 PM

Popular Answer

Two choices are available.

You can just include the pre-existing candidate objects in the task if the context and candidate objects will remain the same. For instance: Make your candidates, then add them to the 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();

Create your job after that:

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

Lastly, include your candidates in the newjob save changes after adding the job to the context and the variable.

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

OR

You can construct a new candidate object and attach it to the context before adding it to the job if you are using a context that is DIFFERENT from the one with which you created the candidates.

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

Set the ID of our candidate object to only.

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

The item should be joined to the new context. Note that because it is already tracking the candidate if the context from the previous example is still present, you won't be able to accomplish this.

newContext.Candidates.Attach(existingCandidate3);

Since we want to use the current candidate rather than create a new one, set the state to Unchanged.

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

Add it, then save the adjustments.

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

Done!



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow