web-dev-qa-db-ja.com

EFを使用した多対多の関係での挿入操作

私は2つのモデルクラスを持っています:

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つのテーブルCandidates、Jobs&CandidatesJobs(EFによって自動生成)を生成します

これで、Jobsテーブルにレコードがあります:Id = 1、Name = "Sales":Id = 2、Name = "Engineer"。

Candidatesテーブルに挿入する新しいCandidateを、Jobsテーブルの2つのレコードに関連付けたいと思います。

候補者を挿入する前に、JobsテーブルのIDを知っています。データベースを呼び出して、Jobsテーブルから詳細を取得したくありません。

Entity Framework 5を使用してこれを行うにはどうすればよいですか?

9
jonahbgoode

これはどう?

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はジョブが「新規」であると見なし、それらを挿入しようとします。 IDしかない場合は、次のことを試すことができます。

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
Henk Mollema

2つのオプションがあります。

同じコンテキストと候補オブジェクトを配置する場合は、既存の候補オブジェクトをジョブに追加するだけです。例:候補者を作成し、データベースに保存します。

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

[〜#〜]または[〜#〜]

候補を作成したコンテキストとは異なるコンテキストを使用している場合は、新しい候補オブジェクトを作成し、ジョブに追加する前にコンテキストにアタッチできます。

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

新しい候補を作成したくないので、状態をUnchangedに設定します。既存の候補を使用するだけです。

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

それを追加し、変更を保存します。

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

完了!

6
cbeckner

非常に簡単な解決策は、外部参照テーブルのVIEWをテーブル(view_tablename_raw)とまったく同じように作成することです。次に、EFでそのビューを外部キーのないエンティティとして更新します。それらの使用からcontext。view_tablename_raw.Add(...)そしてそれはシームレスに動作します。

0
HackTheDj