2017-01-25 13 views
2

私はインターネットレッスンでプロジェクトのためのアプリケーションを計画しています。レッスンプランは、(データベースの最初のアプローチでEntity Frameworkをして生成された)次のモデルから構築されています:2つ以上のモデルを1つのフォームに投稿するにはどうすればよいですか?

public partial class Subject 
{ 
    public int Id { get; set; } 
    public string Hour { get; set; } 
    public string Name { get; set; } 
    public int DayId { get; set; } 
    [Required] 
    public int PlanId { get; set; } 

    public virtual Day Day { get; set; } 
    public virtual Plan Plan { get; set; } 
} 

public partial class Plan 
{ 
    public Plan() 
    { 
     this.Przedmiot = new HashSet<Subjects>(); 
    } 

    public int Id { get; set; } 
    [Required] 
    public string Name { get; set; } 

    public virtual ICollection<Subject> Subject { get; set; } 
} 

私は1つのビューで両方のモデルを表示して問題がないが、私は投稿する方法を見つけ出すように見えることはできません新しい計画を作成するときに両方のモデルをデータベースに追加します。 My View

だから私の質問は、最善のアプローチはここに何で、どのように私は、データベース内のプランテーブルに1つのレコードを作成することができ、この1つのビューでにリンクされている多くの件名レコード:私は私のビューはこのような何かを見てみたいです。

編集:私のディスプレイビュー コード要求として(それはかなり長いですので、不要な部分を省略):

@model IEnumerable<Lesson_plan.DAL.Subject> 
<table style="border: 1px solid black; margin: 40px; width: 100%;"> 
    <tr> 
     <th>Hours</th> 
     <th>Monday</th> 
     <th>Tuesday</th> 
     <th>Wednesday</th> 
     <th>Thursday</th> 
     <th>Friday</th> 
     <th>Saturday</th> 
     <th>Sunday</th> 
    </tr> 

    @{ 
     if (Model != null) 
     { 
      var r = 1; 
      var t = 1; 
      List<string> hours = new List<string>(); 
      foreach (var subject in Model) 
      { 
       if (!hours.Contains(subject.Hour)) 
       { 
        <tr> 
         <td> 
          <textarea>  
          @Html.DisplayFor(modelItem => subjest.Hour) 
          @{ hours.Add(subject.Hour); } 
          </textarea> 
         </td> 

         <td> 
          <textarea> 
          @foreach (var subjectName in Model) 
          { 
           if (subjectName.Day.DayOfTheWeek.Equals("Monday") && 
            subject.Hour.Equals(subjetName.Hour)) 
           { 
            @Html.DisplayFor(modelItem => subject.Name) 
           } 
          } 
          </textarea> 
         </td> 

//and so on for every day 

         } 
        </tr> 
        r++; 
       } 
      } 
     } 
    } 
</table> 

コード私のコントローラクラスの(私が作成方法といくつかの実験をしましたが、私は」メートル、ここで元のメソッドを掲載):フォームとビューの作成のための

namespace Lesson_plan.Controllers 
{ 
    public class PlansController : Controller 
    { 
     private readonly LessonPlanEntities db = new LessonPlanEntities(); 

     // GET: Plans 
     public ActionResult Index() 
     { 
      var plans = db.Plan.ToList(); 
      return View(plans); 
     } 

     // GET: Plans/Details/5 
     public ActionResult Details(int? id) 
     { 
      if (id == null) 
       return Create(); 
      var subjects = db.Subject. 
       Where(x => x.PlanId == id). 
       OrderByDescending(x => x.Hour).ToList(); 
      if (subjects.Count > 0) 
       ViewBag.Title = subjects[0].Plan.Name; 
      return View(subjects); 
     } 

     // GET: Plans/Create 
     public ActionResult Create() 
     { 
      return View(); 
     } 

     [HttpPost] 
     public ActionResult Create(Plan plan) 
     { 
      if (ModelState.IsValid) 
      { 
       db.Plan.Add(plan); 
       db.SaveChanges(); 
       return RedirectToAction("Index"); 
      } 

      return View(plan); 
     } 

     // GET: Plans/Edit/5 
     public ActionResult Edit(int? id) 
     { 
      if (id == null) 
       return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
      var plan = db.Plan.Find(id); 
      if (plan == null) 
       return HttpNotFound(); 
      return View(plan); 
     } 

     // POST: Plans/Edit/5 
     // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
     // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 
     [HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Edit([Bind(Include = "Id,Nazwa")] Plan plan) 
     { 
      if (ModelState.IsValid) 
      { 
       db.Entry(plan).State = EntityState.Modified; 
       db.SaveChanges(); 
       return RedirectToAction("Index"); 
      } 
      return View(plan); 
     } 

     // GET: Plans/Delete/5 
     public ActionResult Delete(int? id) 
     { 
      if (id == null) 
       return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
      var plan = db.Plan.Find(id); 
      if (plan == null) 
       return HttpNotFound(); 
      return View(plan); 
     } 

     // POST: Plans/Delete/5 
     [HttpPost] 
     [ActionName("Delete")] 
     [ValidateAntiForgeryToken] 
     public ActionResult DeleteConfirmed(int id) 
     { 
      var plan = db.Plan.Find(id); 
      db.Plan.Remove(plan); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing) 
       db.Dispose(); 
      base.Dispose(disposing); 
     } 
    } 
} 

EDIT2 コード:

@model Lesson_plan.DAL.Plan 

@using (Html.BeginForm("Create", "Plans")) 
{ 
    <div> 
     @Html.LabelFor(plan => plan.Name)<br/> 
     @Html.TextAreaFor(plan => plan.Name) 
    </div> 
    <table style="border: 1px solid black; margin: 40px; width: 100%;"> 
     <tr> 
      <th>Hours</th> 
      <th>Monday</th> 
      <th>Tuesday</th> 
      <th>Wednesday</th> 
      <th>Thursday</th> 
      <th>Friday</th> 
      <th>Saturday</th> 
      <th>Sunday</th> 
     </tr> 
      @{ 
       for (int i = 0; i < 7; i++) 
       { 
        <tr> 
         //what sould i put here ?      
         <td><textarea></textarea></td> 
         <th><textarea></textarea></th> 
         <th><textarea></textarea></th> 
         <th><textarea></textarea></th> 
         <th><textarea></textarea></th> 
         <th><textarea></textarea></th> 
         <th><textarea></textarea></th> 
         <th><textarea></textarea></th> 
        </tr> 
       } 
      } 
    </table> 
    <p> 
     <a type="button" class="btn btn-info" [email protected]("Index")>Back</a> 
     <input type="submit" value="Create"/> 
    </p> 
} 
+1

「両方のモデルを1つのビューに表示するのに問題はない」と言ったので、両方のモデルを1つのビューにどのように表示するのですか?コントローラーやコードを表示することもできます。 – ekad

+0

タプルを使用できます。 http://www.c-sharpcorner.com/UploadFile/ff2f08/multiple-models-in-single-view-in-mvc/ – Karthikeyan

+0

1つのレコードを 'Plan'テーブルに挿入し、最大7レコードをCreateボタンをクリックすると 'Subject'テーブルが表示されます。それが本当であると仮定すると、毎日のテキストボックスが 'Subject'テーブルに挿入されるものにどのように関係するかを説明できますか?私はテキストボックスに入力されたものがHoursフィールドに 'Subject'テーブルの' Hour'フィールドに挿入されることを理解していますが、 'Monday'や' Wednesday'のテキストボックスに 'abcd'と入力するとどうなりますか?その場合の 'Subject'テーブルの' Name'と 'DayId'フィールドの値はどうなりますか? – ekad

答えて

3

最善のアプローチは、計画(S)および/または件名(S)の両方のために、提出する必要のあるフォーム上のすべてのデータを保持できるのViewModelクラスを設計することです。

このViewModelを受け取るアクションメソッドでは、データを選択し、それに基づいてデータベースに格納するために必要な挿入や更新が行われます。

コントローラのみがデータベースクラスの知識を持っている必要があります。 ViewModelオブジェクトとデータベースオブジェクトの間のすべてのマッピングは、コントローラによって行われなければならず、ビューはこれによって妨げられたり、妨げられたりしてはなりません。

+2

ダウンボッターに追加やコメントがある場合は、私はそれを歓迎します。 –

+0

コントローラーだけがデータベースクラスの知識を持つべきであるという純粋な見解です。人々はあなたが主張するものではなく、皮肉なコントローラ、太ったモデルを購読する傾向があります。 – mattmanser

+0

確かに違いますが、ここでは適切だと思います。便利なリンク:http://softwareengineering.stackexchange.com/questions/257507/should-an-asp-net-mvc-application-directly-use-entity-framework-as-the-model –

0

複数のモデルをビューモデルに結合してビューに送ることができます。しかし、あなたの問題は異なっているようですので、ここでは長い答えが続きます:

DB設計に関する質問では、私はあなたがリレーショナルストレージを使用していると仮定しています。多対多が適所になければならない。件名hereについて詳しく読むことができます。

ウェブアプリケーションの場合、通常は、両方の目的のモデルが含まれているViewModelを作成するだけです。あなたの質問に精緻化していない場合、それは正解になります。しかし、あなたの場合、あなたの2つの "モデル"クラスはすでにリンクされているので、あなたのモデルは単にプランになることができます。

EF6(あなたの生成されたクラスに基づいている)を使用していると仮定しているので、計画の科目は計画とともにポストされます。

singletonを使用して現在の既存のサブジェクトをアプリのどこかにキャッシュし、ポストバックした後、プランにキャッシュされたサブジェクトを繰り返して、DBに既に存在するかどうかを確認する必要があります。そうでない場合は、最初に挿入します(ICollectionにプランに追加するだけです)。次に、EFを使用して計画を挿入する方法を知っているはずです。

途中ではるかに多くのバンプがあるかもしれませんが、それらについて新しい質問をすることができます。あなたの質問は今や広すぎます。

私はあなたに何か働くのを手伝っていますが、おそらく理想的にはならないでしょう。作業を開始したら、ビジネスロジックを置く場所(およびコントローラーを小さくする方法)を読むことをお勧めします。 This記事は良いスタートになるかもしれません。

もう1つのことは、データアクセスを別の層に保存することです。 Goodleの「3層アーキテクチャ」と、this videoをリポジトリパターンでチェックします。

幸運を祈る!

**ポストOP-編集**

[OK]を、あなたのコードを見て、あなたはおそらく、複数の質問に分離したいと思うことを、多くの問題があるように思われます。ここでスタートだ:

  1. あり、あなたのビューには、フォームはありません、あなたは、フォームやビュー上のポストボタン、および[Post]が付いController上のアクションメソッドのバージョンが必要です。 asp.mvcコアのチュートリアルthisと古いバージョンのthisをお勧めします。 「編集」ビューと「表示」ビューで異なるページを作成する場合は、別々のビューを作成するだけですが、作成するときにはフォームが必要になります。
  2. 当面は、プランをviewModelとして使用する必要があります。通常、これは理想的ではありませんが、答えとして本を書く必要がある理由を説明するためです。リンクされているリソースは、その部分を理解するのに役立ちます。
  3. asp.net mvcの古いバージョンを使用しているようです(多分私は間違っていますか?教えてください)。クライアント上の特定の日付に新しい科目を追加する場合は、javascript(jQuery)を使用するか、ReactやAngularなどの完全なクライアントサイドライブラリも使用する必要があります。あなたが完全なフレームワークに精通していない場合は、今のところJQueryに固執しています。これを実現する方法を知りたい場合は、question and answerを調べてください。
  4. APIメソッドと単純な古いMVCメソッドを別のプロジェクトに分けたい場合があります。

**編集2 ** 今、あなたの計画の作成コードを見て、あなたは正しく@Html.TextAreaFor(plan => plan.Name)がサーバーにポストすることができ、入力を作成する方法であることを読んでいるように見えます。

ただし、プラン名にのみ使用しています。

の代わりに(私はこれらのサブジェクト名のためのものであると仮定しています)、以下のテキストエリアを使用してビューにモデルがどの科目を持っているように、これはなりますが、渡されたプランを想定し

@for(int i = 0; i < plan.Subject.Count(); i++) 
{ 
    @Html.TextAreaFor(plan => plan.Subject[i].Name) 
} 

ようなものを使用それらをリストし、それらを編集可能にする方法。

さて、あなたが例えば、いくつかのフィルタリングを行うこともできますので、曜日に基づいてそれらを分離したいようだ:

var monday = 1; 
@for(int i = 0; i < plan.Subject.Where(s => s.DayId == monday).OrderBy(s => s.Hour).Count(); i++) 

7列のそれぞれにこれを貼り付けます。これで、既にそこに存在するすべてのサブジェクトのテキストエリアが作成されます。

新しいビューを動的に作成する場合は、上記のポイント3を参照してください。あなたがまだ科目を持っていない場合は、データベースにいくつかの偽のものを作成してください。ちょうどクライアント上でレンダリングし、ソースコードを確認してから#3でリンクした記事に従ってください。

+0

これは良いスタートです。早急な返信をありがとうございます。しかし、どのように最初の場所でViewから被写体を取り出すことができますか? – Tama

+0

あなたの編集に気づいたようです。特定の問題を確認します。 – nikovn

+0

コメントは要求通りにアイテムを表示するためのコードなので、フォームはありません。フォームと空白のテキストボックスを除き、作成ビューは全く同じです。 – Tama

関連する問題