4

私は何時間も見回しましたが、私の問題を解決するための簡単な方法を見つけることができないようです.

基本的に、テーブルで橋渡しされた 1 対多の関係があります。私のコントローラーは「作成」メソッドを完全に処理しているようで、「1」テーブル内にレコードを作成し、「多」テーブルをブリッジします。

ただし、「編集」メソッドは、ブリッジ テーブルをまったく変更/更新していないようです。私が間違っていること、および「作成」アプローチと異なる理由について何か考えはありますか?

簡潔にするために、次のモデルがあるとしましょう。

public class Incident
{
    [Key]
    public int IncidentID { get; set; }
    public string Title { get; set; }
    public virtual ICollection<IncidentResources> Resources{ get; set; }
}

そしてリソースモデル:

public class Resource
{
    [Key]
    public int ResourceID{ get; set; }
    public int Name { get; set; }
    ...OTHER FIELDS REMOVED FOR BREVITY...
}

そして、ブリッジ テーブルとモデルを介してこれら 2 つをブリッジしています。

public class IncidentResource
{
    [Key]
    public int IncidentResourceID { get; set; }
    public int IncidentID { get; set; }
    public int ResourceID { get; set; }
    public virtual <Resource> Resource { get; set; }
}

私のコントローラーには、次のコードがあります。

[HttpPost]
public ActionResult Create(Incident incident)
{
  //incident.Resources is returned as a valid object...
  if (ModelState.IsValid)
  {        
    db.Incidents.Add(incident);
    db.SaveChanges();
    return RedirectToAction("Index");
  }
  return View(incident);
}

上記は完全に機能します!前述したように、新しいインシデントが適切なテーブルに挿入され、インシデントに割り当てられたすべてのリソースが IncidentResources テーブルに追加されます。

ただし、次のコードは編集のためにこのように機能しません...

[HttpPost]
public ActionResult Edit(Incident incident)
{
  if (ModelState.IsValid)
  {
    //THE USER CAN ADD ADDITIONAL RESOURCES
    foreach (IncidentResource r in incident.Resources)
    {
      r.IncidentID = incident.IncidentID;
    }
    db.Entry(incident).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
  }
  return View(incident);
}

繰り返しますが、上記は IncidentResources テーブルに対して何もしていないように見えます。レコードは追加、削除、または更新されません。私もエラーを受け取りません。それは何もしません。

ブリッジテーブルのデータを破棄して再挿入したくないことに注意してください。孤立させたくないデータに対して 1 対多の関係を持ちます。

これがどのように機能するかについて、私は何を理解していませんか?

4

6 に答える 6

1

EF の外部で作成されたエンティティ インスタンスをアタッチし、それが変更されたことを EF に知らせる必要があります。

追加してみてください:

db.Incidents.Attach(incident);

状態を変更する前に。あなたの場合、コードの最後のブロックは次のようになります。

[HttpPost]
public ActionResult Edit(Incident incident)
{
  if (ModelState.IsValid)
  {
    //THE USER CAN ADD ADDITIONAL RESOURCES
    foreach (IncidentResource r in incident.Resources)
    {
      r.IncidentID = incident.IncidentID;
    }
    db.Incidents.Attach(incident);
    db.Entry(incident).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
  }
  return View(incident);
}
于 2013-01-31T23:18:29.177 に答える
0

現在のコードで、Entity Frameworkは、Incidentオブジェクトがまったく変更されていないことを確認しており、調整が必要なIncidentResourcesがあるかどうかを確認しようとしていないのではないかと思います。

ループに次の行を追加してみてください。

db.Entry(r).State = EntityState.Modified;

編集:この回答を書いた後、私はEntityFrameworkに関するJulieLermanの講演を見ていました。彼女は、「変更された状態はグラフを介してカスケードされない」と述べていました。つまり、上記のコードでそれを行う必要があります。あなたのために。

于 2013-02-05T20:39:36.927 に答える
0

IncidentResourceオブジェクトのIncidentIDは、外部キーとしてIncidentテーブルにマッピングされていないようです。インシデントを指す外部キーとしてIncidentIDを明示的に設定するには、ForeignKeyアノテーションを追加してみてください。

   [ForeignKey("Incident")]
    public int IncidentID { get; set; }
于 2013-02-01T01:35:15.227 に答える
0

可能であれば、IncidentResource テーブルの外部キー IncidentID を主キーに追加して、複合主キーを作成してみてください。私は同様の問題を抱えていましたが、これが私を助けてくれました。

他のいくつかのスタックオーバーフローの質問から解決策を得ました。エンティティ モデルの最初の作業単位アプローチで AutoMapper を使用しているため、セットアップはこれらと正確に一致しませんでしたが、関係テーブルで複合キーを作成することで問題が解決しました。

コレクションから子を削除し、SaveChanges の問題を解決することは可能ですか?

識別関係と非識別関係の違いは何ですか?

于 2013-02-07T17:22:02.317 に答える
0

あなたは次のことをすべきではありませんか

[HttpPost]
public ActionResult Edit(Incident incident)
{
  if (ModelState.IsValid)
  {
    //THE USER CAN ADD ADDITIONAL RESOURCES
    foreach (IncidentResource r in incident.Resources)
    {
      r.IncidentID = incident.IncidentID;
      db.Entry(r).State = EntityState.Modified;
    }
    db.SaveChanges();
    return RedirectToAction("Index");
  }
  return View(incident);
}
于 2013-02-08T09:04:24.390 に答える
0

フォームの非表示フィールドで IncidentID を追跡していない限り、存在しないインシデント (IncidentID:0) を更新しようとしていることが問題の原因であるに違いありません。

これはルートによって異なりますが、デフォルトのルート パターンを想定すると、次のようになります。

[HttpPost]
public ActionResult Edit(int id, Incident incident)
{
  incident.IncidentID = id;

  if (ModelState.IsValid)
  {
    //THE USER CAN ADD ADDITIONAL RESOURCES
    foreach (IncidentResource r in incident.Resources)
    {
      r.IncidentID = incident.IncidentID;
    }
    db.Entry(incident).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
  }
  return View(incident);
}
于 2013-02-06T08:28:19.413 に答える