<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      MVC3+EF4.1學習系列(六)-----導航屬性數據更新的處理

      文章索引和簡介

      通過上一篇的學習 我們已經知道怎么查詢關系 這篇就來說說怎么導航屬性數據更新時的處理 以及EF又會為我們生成哪些SQL~

      老規矩 先看下今天的圖

      添加和修改頁面基本就是這樣

      這節的內容相對簡單~~

      主要就是講  一對一 一對多 多對多時的增刪改 以及MVC的一些小東西

      一. 一對多的的處理

      看第一張圖   院系和課程是一對多的關系  

      1.添加

      一對多的添加非常簡單  遇到一對多的情況  我們一般考慮dropdownlist來展示 只要把這個展示出來就容易了

      mvc綁定dropdownlist 一般是 控制器用 viewstate存一個SelectList  或者viewbag  然后視圖綁定 上代碼

      課程添加控制器
              public ActionResult Create()
      {
      PopulateDepartmentsDropDownList();

      return View();
      }

      //
      // POST: /Course/Create

      [HttpPost]
      public ActionResult Create(Course course)
      {
      try
      {
      // TODO: Add insert logic here
      if (ModelState.IsValid)
      {
      db.Courses.Add(course);
      db.SaveChanges();
      // PopulateDepartmentsDropDownList(course.DepartmentID);
      }
      return RedirectToAction("Index");
      }
      catch
      {
      ModelState.AddModelError(
      "", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");

      return View();
      }


      }

      /// <summary>
      /// 處理下拉列表
      /// </summary>
      /// <param name="selected">選擇的項</param>
      private void PopulateDepartmentsDropDownList(object selected = null)
      {
      var departmentsQuery
      = from d in db.Departments
      orderby d.Name
      select d;
      ViewBag.DepartmentID
      = new SelectList(departmentsQuery, "DepartmentID", "Name", selected);
      }

      可以看到 非常簡單下面是視圖的

      視圖
      @model ContosoUniversity.Models.Course

      @{
      ViewBag.Title = "Create";
      Layout = "~/Views/Shared/_Layout.cshtml";
      }

      <h2>Create</h2>

      <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
      <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

      @using (Html.BeginForm()) {
      @Html.ValidationSummary(true)
      <fieldset>
      <legend>Course</legend>
      <div class="editor-label">
      @Html.LabelFor(model => model.CourseID)
      </div>
      <div class="editor-field">
      @Html.EditorFor(model => model.CourseID)
      @Html.ValidationMessageFor(model => model.CourseID)
      </div>


      <div class="editor-label">
      @Html.LabelFor(model => model.Title)
      </div>
      <div class="editor-field">
      @Html.EditorFor(model => model.Title)
      @Html.ValidationMessageFor(model => model.Title)
      </div>

      <div class="editor-label">
      @Html.LabelFor(model => model.Credits)
      </div>
      <div class="editor-field">
      @Html.EditorFor(model => model.Credits)
      @Html.ValidationMessageFor(model => model.Credits)
      </div>

      <div class="editor-label">
      @Html.LabelFor(model => model.DepartmentID, "Department")
      </div>
      <div class="editor-field">
      @Html.DropDownList("DepartmentID","請選擇")
      @Html.ValidationMessageFor(model => model.DepartmentID)
      </div>

      <p>
      <input type="submit" value="Create" />
      </p>
      </fieldset>
      }

      <div>
      @Html.ActionLink("Back to List", "Index")
      </div>

      視圖的核心其實就這句

      Html.DropDownList("DepartmentID","請選擇")
      DepartmentID 對應 你的viewbag  就能讓他們對應上去了 就這么簡單神奇~~  由于生成的html  name 為 DepartmentID 當你保存的時候 通過ModelBinder  
      會自動對應到實體類上 直接保存即可
      生成的SQL插入語句也簡單 而且是參數化的~
      exec sp_executesql N'insert [dbo].[Course]([CourseID], [Title], [Credits], [DepartmentID])
      values (@0, @1, @2, @3)
      ',N'@0 int,@1 nvarchar(50),@2 int,@3 int',@0=4444,@1=N'試試插入',@2=4,@3=1

      2.修改

      這個沒啥好說的了~~ 基本和添加一樣

      修改控制器
        public ActionResult Edit(int id)
      {
      Course course
      = db.Courses.Find(id);
      PopulateDepartmentsDropDownList(course.DepartmentID);
      return View(course);

      }

      //
      // POST: /Course/Edit/5

      [HttpPost]
      public ActionResult Edit(Course course)
      {
      try
      {
      if (ModelState.IsValid)
      {
      db.Entry(course).State
      = EntityState.Modified;
      db.SaveChanges();
      return RedirectToAction("Index");
      }
      }
      catch (DataException)
      {
      //Log the error (add a variable name after DataException)
      ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
      }
      PopulateDepartmentsDropDownList(course.DepartmentID);
      return View(course);

      }

      生成的SQL語句如下

      exec sp_executesql N'update [dbo].[Course]
      set [Title] = @0, [Credits] = @1, [DepartmentID] = @2
      where ([CourseID] = @3)
      ',N'@0 nvarchar(50),@1 int,@2 int,@3 int',@0=N'試試插入',@1=4,@2=2,@3=4444

      這有個問題  就是把每個字段都做了更新 而我們實際上只更新了一個  如果能按需更新改多好 dudu給了我們好的思路 可以參考下 -----文章連接

      3.刪除

      這個簡單....沒啥好說的了  具體參考第二篇  簡單的增刪改查~~

      二.一對一和多對多

      一對多比較簡單 因為涉及的都是一張表里的東西 所以沒什么難的   而一對一,多對多 則是處理 多張表的情況 所以這里重點說下這部分~~

      先看第二個圖 分析下關系   這是修改老師的信息  跟他關聯的有一對一的地址  和多對多的課程  也就是說  當我們插入一條記錄時 

      應該插入三張表  教師表  辦公地址表  和 教師課程關系表   那讓我們來印證下吧

      1.添加

      首先 我們要先把添加頁面顯示出來 先來說下 下面那個復選框選擇課程   控制器很簡單 就是讀取出來所有課程存放到viewbag里即可

      public ActionResult Create()
      {
      ViewBag.SelectCourse
      = db.Courses.ToList();

      return View();
      }

      視圖的顯示 有兩種方法  一種是原文提供的
      添加一個viewmodel  專門存放課程 以及是否選中  然后通過如下代碼實現三列換行

      原文的方法
      <div class="editor-field">
      <table style="width: 100%">
      <tr>
      @{
      int cnt = 0;
      List
      <ContosoUniversity.ViewModels.AssignedCourseData> courses = ViewBag.Courses;

      foreach (var course in courses) {
      if (cnt++ % 3 == 0) {
      @:
      </tr> <tr>
      }
      @:
      <td>
      <input type="checkbox"
      name
      ="selectedCourses"
      value
      ="@course.CourseID"
      @(Html.Raw(course.Assigned ? "checked
      =\"checked\"" : "")) />
      @course.CourseID @:
      &nbsp; @course.Title
      @:
      </td>
      }
      @:
      </tr>
      }
      </table>
      </div>

      個人覺得麻煩了些  這里我說下我的方法

         <div class="editor-field">
      @{
      System.Text.StringBuilder sb = new System.Text.StringBuilder("
      <table style='width:100%'><tr>");
      List
      <ContosoUniversity.Models.Course> list= ViewBag.SelectCourse as List<ContosoUniversity.Models.Course>;
      for (int i = 0; i
      < list.Count; i++)
      {
      if (i!
      =0&&i % 3 == 0)
      {
      sb.Append("</tr
      ><tr>");
      }
      sb.Append("
      <td><input type='checkbox' value='"+list[i].CourseID+"' name='selectedCourses'/>"+list[i].Title+"</td>");
      }
      sb.Append("
      </tr></table> ");
      }
      @MvcHtmlString.Create(sb.ToString())
      </div>

      這里要說的就是 MvcHtmlString.Create   如果不使用這個 直接輸入  則會把<tr><td> 這些也直接輸入出來 而不是轉換成HTML   記住,如果想生成想要的結果 請使用MvcHtmlString.Create


      好了 添加頁面有了 現在就是添加了 

      添加
      [HttpPost]
      public ActionResult Create(Instructor Model, string[] selectedCourses)
      {
      try
      {
      // TODO: Add insert logic here
      if (ModelState.IsValid)
      {

      Model.Courses
      = new List<Course>();

      foreach (var item in db.Courses.ToList())
      {
      if (selectedCourses.Contains(item.CourseID.ToString()))
      {
      Model.Courses.Add(item);
      }
      }
      db.Instructors.Add(Model);
      db.SaveChanges();

      }
      return RedirectToAction("Index");

      }
      catch
      {
      return View();
      }
      }

      這里提下 第二個參數 就是我們選中的checkbox 的value 的集合   這個參數的名字 與 checkbox名字的name一樣

      然后我們遍歷所有的課程  把符合條件的加入進來 我選了一個  讓我們看下EF為我們生成的SQL

      exec sp_executesql N'insert [dbo].[Instructor]([LastName], [FirstName], [HireDate])
      values (@0, @1, @2)
      select [InstructorID]
      from [dbo].[Instructor]
      where @@ROWCOUNT > 0 and [InstructorID] = scope_identity()
      ',N'@0 nvarchar(50),@1 nvarchar(50),@2 datetime',@0=N'W',@1=N'LF',@2='02 3 2011 12:00:00:000AM'



      exec sp_executesql N'insert [dbo].[CourseInstructor]([CourseID], [InstructorID])
      values (@0, @1)
      ',N'@0 int,@1 int',@0=2042,@1=10




      exec sp_executesql N'insert [dbo].[OfficeAssignment]([InstructorID], [Location])
      values (@0, @1)
      ',N'@0 int,@1 nvarchar(50)',@0=10,@1=N'天朝'

      看 確實是生成了三條SQL語句 符合我們的要求 而我們的代碼 卻寫了很少  就輕松完成了添加~~

      2.修改

      修改要比添加麻煩   首先顯示視圖時  要顯示哪些被選中了 還有就是修改時  要在關系表里刪除原來的 課程教師關系 還要添加新的進去

      如何讓EF幫我們完成這一對一 多對多的復雜的 三張表之間的關系處理呢

      還是先從視圖開始 先解決讓以前被選中的顯示出來

              public ActionResult Edit(int id)
      {
      ViewBag.SelectCourse
      = db.Courses.ToList();
      Instructor model
      = db.Instructors.Include(i => i.Courses).Include(i => i.OfficeAssignment).Where(i => i.InstructorID == id).SingleOrDefault();
      return View(model);
      }

      先把要修改的這條加載出來返回給視圖   用貪婪加載 把地點和課程都加載出來

      修改視圖
            <div class="editor-field">
      @{
      System.Text.StringBuilder sb = new System.Text.StringBuilder("
      <table style='width:100%'><tr>");
      List
      <ContosoUniversity.Models.Course> list= ViewBag.SelectCourse as List<ContosoUniversity.Models.Course>;
      for (int i = 0; i
      < list.Count; i++)
      {
      if (i!
      =0&&i % 3 == 0)
      {
      sb.Append("</tr
      ><tr>");
      }

      string IsSelect = string.Empty;
      if (Model.Courses.Contains(list[i]))
      {
      IsSelect = "checked='checked'";
      }
      sb.Append("
      <td><input type='checkbox' value='"+list[i].CourseID+"' "+IsSelect+" name='selectedCourses'/>"+list[i].Title+"</td>");
      }
      sb.Append("
      </tr></table> ");
      }
      @MvcHtmlString.Create(sb.ToString())
      </div>

      在視圖上加上判斷 遍歷到的這個課程 是否在選中的課程里 如果在 則加上選中屬性

       string IsSelect = string.Empty;
      if (Model.Courses.Contains(list[i]))
      {
      IsSelect = "checked='checked'";
      }

      這樣就解決了視圖修改時的顯示問題了 下面是點擊修改時  讓我們先大概想想 有哪些操作

      1.修改 教師表信息

      2.修改 地址表信息

      3. 刪除以前的課程關系表  和添加新的課程關系表記錄

      這里比較負責的是第三部  我們來想想怎么做 現在 我們能知道 我們新選擇了哪些  和 以前選擇了哪些   比如 新選擇的是 {1,2,3}  這次選的是 {3,4,5} 那么我們應該

      刪除{4,5}  添加{1,2} 即可 這其實就轉換為一個簡單的算法題了~~ 原文給出了一種方法  我自己也寫了一種  大家可以比較下看~先上原文的

      原文修改核心代碼
      private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
      {
      if (selectedCourses == null)
      {
      instructorToUpdate.Courses
      = new List<Course>();
      return;
      }

      var selectedCoursesHS
      = new HashSet<string>(selectedCourses);
      var instructorCourses
      = new HashSet<int>
      (instructorToUpdate.Courses.Select(c
      => c.CourseID));
      foreach (var course in db.Courses)
      {
      if (selectedCoursesHS.Contains(course.CourseID.ToString()))
      {
      if (!instructorCourses.Contains(course.CourseID))
      {
      instructorToUpdate.Courses.Add(course);
      }
      }
      else
      {
      if (instructorCourses.Contains(course.CourseID))
      {
      instructorToUpdate.Courses.Remove(course);
      }
      }
      }
      }

      原文利用HashSet 不能存重復項 實現  不過判斷邏輯多了些 但效率應該高  hashset 散列算法

      下面是我的

           private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructor)
      {
      if (selectedCourses == null)
      {
      instructor.Courses
      = new List<Course>();
      return;
      }
      //思路 比較以前選擇的和現在選擇的 先取出他們的差集 那么這部分就是可以刪除的項 和添加的部分
      string[] beforeSelect=instructor.Courses.Select(i => i.CourseID.ToString()).ToArray();//得到以前選擇的
      beforeSelect.Except(selectedCourses).ToList().ForEach(n => instructor.Courses.Remove(db.Courses.Find(Convert.ToInt32(n))));
      selectedCourses.Except(beforeSelect).ToList().ForEach(n
      => instructor.Courses.Add(db.Courses.Find(Convert.ToInt32(n))));
      }

      這里 參數selectedCourses 為現在選中的項   利用linq 內置的方法 Except取出差集  然后 ForEach遍歷移除和添加   一句話搞定  但是效率估計不會太高~~

      下面是完整的修改方法

      完整修改方法
       [HttpPost]
      public ActionResult Edit(int id, FormCollection collection, string[] selectedCourses)
      {
      try
      {
      // TODO: Add update logic here
      var instructor = db.Instructors.Include(i => i.Courses).Where(i => i.InstructorID == id).SingleOrDefault();

      UpdateModel(instructor,
      "", null, new string[] {"Courses"});
      UpdateInstructorCourses(selectedCourses, instructor);
      if (string.IsNullOrWhiteSpace(instructor.OfficeAssignment.Location))
      {
      instructor.OfficeAssignment
      = null;
      }
      db.Entry(instructor).State
      = EntityState.Modified;
      db.SaveChanges();
      return RedirectToAction("Index");
      }
      catch
      {
      return View();
      }
      }

      private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructor)
      {
      if (selectedCourses == null)
      {
      instructor.Courses
      = new List<Course>();
      return;
      }
      //思路 比較以前選擇的和現在選擇的 先取出他們的差集 那么這部分就是可以刪除的項 和添加的部分
      string[] beforeSelect=instructor.Courses.Select(i => i.CourseID.ToString()).ToArray();//得到以前選擇的
      beforeSelect.Except(selectedCourses).ToList().ForEach(n => instructor.Courses.Remove(db.Courses.Find(Convert.ToInt32(n))));
      selectedCourses.Except(beforeSelect).ToList().ForEach(n
      => instructor.Courses.Add(db.Courses.Find(Convert.ToInt32(n))));
      }

      好了 讓我們來看下執行的SQL

      exec sp_executesql N'update [dbo].[Instructor]
      set [LastName] = @0, [FirstName] = @1, [HireDate] = @2
      where ([InstructorID] = @3)
      ',N'@0 nvarchar(50),@1 nvarchar(50),@2 datetime,@3 int',@0=N'W',@1=N'LF',@2='02 3 2011 12:00:00:000AM',@3=10



      exec sp_executesql N'update [dbo].[OfficeAssignment]
      set [Location] = @0
      where ([InstructorID] = @1)
      ',N'@0 nvarchar(50),@1 int',@0=N'',@1=10



      exec sp_executesql N'delete [dbo].[CourseInstructor]
      where (([CourseID] = @0) and ([InstructorID] = @1))
      ',N'@0 int,@1 int',@0=2042,@1=10
      exec sp_executesql N'insert [dbo].[CourseInstructor]([CourseID], [InstructorID])
      values (@0, @1)
      ',N'@0 int,@1 int',@0=0,@1=10

      看 和我們想要的效果一樣~~

      3.刪除

      簡單的說下刪除, 當我們刪除一條數據時 直接看生成的SQL語句  預計應該是 要刪3個表

      exec sp_executesql N'insert [dbo].[CourseInstructor]([CourseID], [InstructorID])
      values (@0, @1)
      ',N'@0 int,@1 int',@0=0,@1=10

      exec sp_executesql N'delete [dbo].[OfficeAssignment]
      where ([InstructorID] = @0)
      ',N'@0 int',@0=10

      結果是刪除了 2個表的  一對一的刪除了  可是多對多的為什么沒刪除 這其實是一個簡單的數據庫知識了~~

      EF為我們創建數據庫時  這個刪除規則是層疊  就是級聯刪除  所以這個關系表的就會被直接刪除了

      三.總結

      導航屬性的更新操作等 結束了   現在EF的已經基本操作已經結束了  下一節講EF處理并發的策略

      posted on 2011-08-01 08:56  wlf  閱讀(16193)  評論(19)    收藏  舉報

      主站蜘蛛池模板: 尤物yw193无码点击进入| 久久96热人妻偷产精品| 国产精品高清视亚洲中文| 无码人妻斩一区二区三区| 成人亚欧欧美激情在线观看| 亚洲全乱码精品一区二区| 国产性生大片免费观看性| 日韩V欧美V中文在线| 日本视频一两二两三区| 精品国产一区二区三区2021 | 风流少妇树林打野战视频 | 欧美日韩不卡视频合集| 色偷偷成人综合亚洲精品| 樱花草视频www日本韩国| 郎溪县| 国产一区二区三区亚洲精品| 波多野结衣久久一区二区| 亚洲国产精品久久久天堂麻豆宅男 | 亚洲欧洲av一区二区久久| 又黄又刺激又黄又舒服| 午夜欧美精品久久久久久久| 亚洲精品一区二区三天美| 亚洲欧洲无码av电影在线观看| 日本人一区二区在线观看| 国产成人精彩在线视频| 亚洲欧美高清在线精品一区二区| 毛多水多高潮高清视频| 国产精品久久久久精品日日| 亚洲欧美一区二区成人片| 日本韩国一区二区精品| 偷拍精品一区二区三区| 亚洲成人av免费一区| 久久精品人人做人人爽电影蜜月| 国产人妻大战黑人20p| 人人妻人人狠人人爽天天综合网| 狠狠躁夜夜躁人人爽蜜桃| 成熟妇女性成熟满足视频| 国产精品成人中文字幕| 江达县| 日本国产精品第一页久久| AV毛片无码中文字幕不卡|