简体   繁体   English

使用EF插入具有多对多关系的操作

[英]Insert operation with many-to-many relationship using EF

I've two model classes: 我有两个模型类:

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

My DbContext name is JobsContext. 我的DbContext名称是JobsContext。

The above code generates me 3 tables Candidates, Jobs & CandidatesJobs(autogenerated by EF) 上面的代码生成了3个表候选人,工作和候选人工作(由EF自动生成)

Now I've records in Jobs table : Id = 1, Name = "Sales" : Id = 2, Name = "Engineer". 现在我在Jobs表中记录:Id = 1,Name =“Sales”:Id = 2,Name =“Engineer”。

I want to associate a new Candidate which I'll be inserting into Candidates table with the 2 records from Jobs table. 我想将一个新的Candidate与Jobs表中的2个记录关联到Candidates表中。

Before inserting the Candidate I know the Id's of the Jobs table & I don't wish to make a call to the database to get more details from Jobs table. 在插入候选人之前,我知道了Jobs表的Id,我不想调用数据库来从Jobs表中获取更多细节。

How do I do this using Entity Framework 5? 如何使用Entity Framework 5执行此操作?

How about 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 works if you already fetched the jobs from the database within the same instance of the DbContext , else EF will think that the jobs are 'new' and tries to insert them. 这仅在您已在DbContext的同一实例中从数据库中提取作业DbContext ,否则EF会认为作业是“新”并尝试插入它们。 If you only have the ids, you could try the following: 如果您只有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();

There are two options. 有两种选择。

If you are going to have the same context and candidate objects laying around, you can simply add the existing candidate objects to the job. 如果您要使用相同的上下文和候选对象,则只需将现有候选对象添加到作业中即可。 For example: Create your candidates and save 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();

Then, create your job: 然后,创建你的工作:

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

Finally, add your candidates to the new job variable, add the job to the context and save changes. 最后,将候选项添加到新job变量,将作业添加到上下文并保存更改。

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

OR 要么

If you are using a DIFFERENT context from the one you created the candidates with, then you can create a new candidate object and attach it to the context prior to adding it to the job. 如果您使用的是创建候选对象的不同上下文,则可以在将其添加到作业之前创建新的候选对象并将其附加到上下文。

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

Create our candidate object by setting only the ID 通过设置ID来创建候选对象

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

Attach the object to the new context. 将对象附加到新上下文。 Note: if the context from the example above is still around, it will not let you do this since it is already tracking the candidate. 注意:如果上面示例中的上下文仍然存在,则不会允许您执行此操作,因为它已经在跟踪候选项。

newContext.Candidates.Attach(existingCandidate3);

Set the state to Unchanged since we don't want to create a new candidate, just use the existing one. 将状态设置为Unchanged,因为我们不想创建新的候选项,只需使用现有的候选项。

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

Add it and save the changes. 添加并保存更改。

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

Done! 完成!

A very simple solution is to create a VIEW of the xref table exactly as the table (view_tablename_raw). 一个非常简单的解决方案是创建外部参照表的VIEW,与表(view_tablename_raw)完全相同。 Then update that view in EF as an entity without foreign keys. 然后在EF中将该视图更新为没有外键的实体。 From their use context .view_tablename_raw.Add(...) and it will work seamlessly. 从他们的使用上下文 .view_tablename_raw.Add(...),它将无缝地工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM