Создал в базе MSSQL 2 таблички – Players, Teams. Работал в Management Studio
Они связаны внешним ключиком Players_Teams, создавал его так
И нажал на Сохранить.
В Visual Studio создал модели
Player
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace modelsTraining2.Models { public class Player { public int Id { get; set; } public string Name { get; set; } public string Age { get; set; } public string Position { get; set; } public int? TeamId { get; set; } public Team Team { get; set; } } } |
Здесь у нас ключик TeamId, который должен быть образован как имя класса на который ссылается плюс Id. И Team – навигационное свойство
Team
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace modelsTraining2.Models { public class Team { public int Id { get; set; } public string Name { get; set; } public string Coach { get; set; } public ICollection<Player> Players { get; set; } public Team() { Players = new List<Player>(); } } } |
Далее, создал по шаблонам CRUD и представления. Автоматически сгенерировался такой код
PlayersController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Threading.Tasks; using System.Net; using System.Web; using System.Web.Mvc; using modelsTraining2.Models; namespace modelsTraining2.Controllers { public class PlayersController : Controller { private SoccerContext db = new SoccerContext(); // GET: Players public async Task<ActionResult> Index() { var players = db.Players.Include(p => p.Team); return View(await players.ToListAsync()); } // GET: Players/Details/5 public async Task<ActionResult> Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Player player = await db.Players.FindAsync(id); if (player == null) { return HttpNotFound(); } return View(player); } // GET: Players/Create public ActionResult Create() { ViewBag.TeamId = new SelectList(db.Teams, "Id", "Name"); return View(); } // POST: Players/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see https://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Create([Bind(Include = "Id,Name,Age,Position,TeamId")] Player player) { if (ModelState.IsValid) { db.Players.Add(player); await db.SaveChangesAsync(); return RedirectToAction("Index"); } ViewBag.TeamId = new SelectList(db.Teams, "Id", "Name", player.TeamId); return View(player); } // GET: Players/Edit/5 public async Task<ActionResult> Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Player player = await db.Players.FindAsync(id); if (player == null) { return HttpNotFound(); } ViewBag.TeamId = new SelectList(db.Teams, "Id", "Name", player.TeamId); return View(player); } // POST: Players/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see https://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Edit([Bind(Include = "Id,Name,Age,Position,TeamId")] Player player) { if (ModelState.IsValid) { db.Entry(player).State = EntityState.Modified; await db.SaveChangesAsync(); return RedirectToAction("Index"); } ViewBag.TeamId = new SelectList(db.Teams, "Id", "Name", player.TeamId); return View(player); } // GET: Players/Delete/5 public async Task<ActionResult> Delete(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Player player = await db.Players.FindAsync(id); if (player == null) { return HttpNotFound(); } return View(player); } // POST: Players/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<ActionResult> DeleteConfirmed(int id) { Player player = await db.Players.FindAsync(id); db.Players.Remove(player); await db.SaveChangesAsync(); return RedirectToAction("Index"); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } } } |
TeamsController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Threading.Tasks; using System.Net; using System.Web; using System.Web.Mvc; using modelsTraining2.Models; namespace modelsTraining2.Controllers { public class TeamsController : Controller { private SoccerContext db = new SoccerContext(); // GET: Teams public async Task<ActionResult> Index() { return View(await db.Teams.ToListAsync()); } // GET: Teams/Details/5 public async Task<ActionResult> Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Team team = await db.Teams.Include(t=>t.Players).FirstOrDefaultAsync(t=>t.Id==id); if (team == null) { return HttpNotFound(); } return View(team); } // GET: Teams/Create public ActionResult Create() { return View(); } // POST: Teams/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see https://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Create([Bind(Include = "Id,Name,Coach")] Team team) { if (ModelState.IsValid) { db.Teams.Add(team); await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(team); } // GET: Teams/Edit/5 public async Task<ActionResult> Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Team team = await db.Teams.FindAsync(id); if (team == null) { return HttpNotFound(); } return View(team); } // POST: Teams/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see https://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Edit([Bind(Include = "Id,Name,Coach")] Team team) { if (ModelState.IsValid) { db.Entry(team).State = EntityState.Modified; await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(team); } // GET: Teams/Delete/5 public async Task<ActionResult> Delete(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Team team = await db.Teams.FindAsync(id); if (team == null) { return HttpNotFound(); } return View(team); } // POST: Teams/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<ActionResult> DeleteConfirmed(int id) { Team team = await db.Teams.FindAsync(id); db.Teams.Remove(team); await db.SaveChangesAsync(); return RedirectToAction("Index"); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } } } |
Ну и много представлений. Я изменил только одно. TeamsDetails, добавил этот участок кода.
1 2 3 4 5 6 7 8 9 10 |
<dt>Players</dt> <dd> @foreach (var player in Model.Players) { <p>@player.Name (@player.Position)</p> } </dd> |
Представления здесь приводить не буду. Их можно сгенерировать в студии и посмотреть.
Ну и пара скриншотов.
Players/Index
Здесь видно, что каждому игроку соответствует какая-то команда.
Teams/Index
Здесь видно какие игроки в команде.