2016-04-22 5 views
0

私はC#の初心者です。 ASP.NET MVCとEntity Framework 6のWebサイトプロジェクトに取り組んでいます。これまでのところ、私は助けを求める必要はありませんでしたが、デッドロックに達しました。dropdrownlist(ASP.NET MVC)でエンティティを更新する方法

私のプロジェクトの目的は、フォルダに保存されているドキュメントを一覧表示し、データベースに登録し、並べ替え可能なテーブルを持つWebページ上のすべてのドキュメントを表示することです。各文書には「Referentiel」(必要に応じて部門またはカテゴリ)があり、編集可能にする必要があります。これは私が立ち往生している場所です。ドキュメントの各フィールドを編集するためのフォームを含むビューを作成しました。しかし、私のモデルには仮想属性 "Referentiel"があります。これは文字列属性(モデルがそれらの属性を持つデータベースに適合する)ほど簡単には更新できません。

私のモデルですが、私は多くのドキュメントを所有するReferentielとReferentielsを所有するドキュメントを持っています:1対多の関係。 ReferentielクラスのDocumentリストとDocumentのReferentiel属性で実装しました。

public class Document 
{ 
    public int Id { get; set; } // unique identifier 
    public string Code { get; set; } // identifier of a document inside the company 
    public string Titre { get; set; } // name of the saved file (pdf, word...) 
    public string Type { get; set; } // specify the nature of the document 
    public int Ref_Id {get; set;} // foreign identifier with the linked entity in a one-to-many relation. 
    [ForeignKey("Id_Ref")] 
    public virtual Referentiel Referentiel { get; set; } // company's department where the document belongs to. 
} 

public class Referentiel 
{ 
    public int Id { get; set; } // unique identifier 
    public string Nom { get; set; } // name of a company's department 
    public virtual List<Document> Documents { get; set; } // collection of object Document (N.B. : doesn't appear in the database) 
} 

私は、私の見解では両方のモデルにアクセスするためのViewModelを使用していたので、私はDocFormViewModel製:私のコントローラは二つの方法、GETリクエスト用とPOSTリクエストのための1つを持っている

public class DocFormViewModel 
{ 
    public List<Models.Referentiel> Referentiels { get; set; } 
    public Models.Document Doc { get; set; } 

    [Display(Name = "Référentiel")] 
    public int SelectedReferentielId { get; set; } 
} 

を。

// GET: Documents/Modifier/5 
    [HttpGet] 
    public ActionResult Modifier(int? id) 
    { 
     if (id == null) 
     { 
      return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 

     vm.Doc = db.Documents.Find(id); 

     if (vm.Doc == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(vm); 
    } 

    // POST: Documents/Modifier/5 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Modifier([Bind(Include = "Id,Code,Titre,Type,Referentiel")] Document doc) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Entry(doc).State = EntityState.Modified; 
      db.SaveChanges(); 
      return RedirectToAction("Index", "Accueil"); 
     } 

     DocFormViewModel documentReferentielViewModel = new DocFormViewModel 
     { 
      Doc = db.Documents.Find(doc.Id), 
      Referentiels = db.Referentiels.ToList(), 
      SelectedReferentielId = doc.Referentiel.Id, 

     }; 
     ViewBag.referentiel_Id = new SelectList(db.Referentiels.ToList(), "Id", "Referentiels", doc.Referentiel.Id); 

     return View(documentReferentielViewModel); 
    } 

最後に、dropdownListを使用して既存のReferentielを収集します。選択された参照先は、編集された文書を更新するために選択されます。しかし、私は、フォームを送信すると、私の文書は、私はあなたが私を理解願ってい

@model BaseDoc_OI_GRC.ViewModels.DocFormViewModel 

<!--Some html--> 
@using (Html.BeginForm()) 
{ 
    <div class="form-group"> 
     @Html.LabelFor(model => model.SelectedReferentielId, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10">   
      @Html.DropDownListFor(m => m.Doc.Referentiel.Id, Model.ReferentielItems) 
       @Html.ValidationMessageFor(m => m.Doc.Referentiel, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

<div class="form-group"> 
    <div class="col-md-offset-2 col-md-10"> 
     <input type="submit" value="Enregistrer" class="btn btn-default" /> 
    </div> 
</div> 
} 

(データベースでは、ビューで)そのデフォルトReferentielを維持し、私はネイティブスピーカーではないが、私は明確に滞在する私の最善を試してみました。 (いくつかの変数名はフランス語であり、それは心配するべきではありませんが、より良い翻訳が必要な場合は私に尋ねてください)。

お読みいただきありがとうございます。私は非常に感謝しています。 ;)

+0

が.State = EntityState.Modified 'db.Entry(doc.Referentiel)を追加するようにしてください;' 'db.SaveChanges(前);'子エンティティにも変更済みのフラグを立てる必要があるかもしれません。 – Eric

+0

@エリック私もそれについて考えましたが、試していませんでした。だから、私のコードを変更しましたが、例外がスローされます: 'タイプ 'BaseDoc.Models.Referentielのアタッチは別のエンティティが同じプライマリキー値を持つため失敗しました。'モデルの検証を無視すると、別のモデルReferentielが関連する各モデルを更新するのではなく、データベースを更新します。 –

+0

コードには複数の問題があります。最初に 'Document'はその関係を定義するプロパティ(例えば' int ReferentielId')を持っていないようです。次に、データモデルを含むビューモデルがあります(これを行うことはなく、[MVCのViewModelとは何か?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc)を読むことをお勧めします。 )。次に、 'Modifier()' GETメソッドは 'Document'のインスタンスをビューに返しますが、表示されたビューには' @model DocFormViewModel'があります。 –

答えて

0

私は昨日問題を修正しました。あなたの答えをありがとう。私は、エンティティDocumentをエンティティReferentielにリンクするために、私のDalクラス(データアクセスレイヤ)のメソッドを使用しました。この方がはるかに簡単で、何も例外をスローしません(前に投げていなくても)。 DocumentsControllerで私の新しいModifierまたは「編集」方法をまとめると

[HttpPost] 
public ActionResult Modifier(DocFormViewModel viewModel){ 
    dal.ModifierType(viewModel.Doc.Id, viewModel.SelectedTypeString); 
    dal.AjouterDocumentAReferentiel(viewModel.Doc.Id, viewModel.SelectedReferentielId); // English : AddDocumentToReferentiel(id_Document, id_Referentiel) 
    return RedirectToAction("Index", "Accueil"); 
} 

ここでは修正されたパラメータを持つビューのサンプルです:

<!--some-html--> 
@using(Html.BeginForm()) 
{ 
    <!--some-html--> 
    <div class="form-group"> 
     @Html.LabelFor(model => model.SelectedReferentielId, htmlAttributes: new {@class = "control-label col-md-2" }) 
     @Html.DropDownListFor(model => model.SelectedReferentielId, Model.ReferentielItems) 
     @Html.ValidationMessageFor(model => model.SelectedReferentielId, "", new { @class = "text-danger" }) 
    </div> 
} 

マイダルクラスが選択するためのメソッドを持っています更新エンティティ:

// Dal implements an interface IDal which extends IDisposable 
public class Dal : Idal 
{ 
    private BddContext bdd; // BddContext extends DbContext with DbSet<Document> Documents and DbSet<Referentiel> Referentiels attributes 

    // there are some attributes to fetch files from a folder but there're irrelevant to this issue so I skip them and their methods. 
    // Obviously there are a lot more of method to edit, create, remove, 
    // fetch or test existence in database/folder 

    /** 
    * This is the method I used in DocumentController instead of 
    * a direct access to the database with BddContext, now Dal does it instead 
    */ 
    public void AjouterDocumentAReferentiel(int idDoc, int idRef) 
    { 
     Document document = bdd.Documents.FirstOrDefault(doc => doc.Id == idDoc); 
     Referentiel referential = bdd.Referentiels.FirstOrDefault(r => r.Id == idRef) 
     referential.Documents.Add(document); 
     bdd.SaveChanges(); 
    } 
} 

最後に、これは次のとおりです。最終結果:(プライマリページのスクリーンショット)

Homepage where every documents in a folder are registered in the database Edit page for document with id = 1

関連する問題