你的位置:首页 > ASP.net教程

[ASP.net教程]3.CRUD Operations Using Entity Framework 6.0 Code First Approach in MVC【EF 6.0 Code


本来不想写这篇的,因为感觉增删查改,实在是太Easy了。好了,为了巩固学习,还是继续吧:

打算实现书籍的增删查改,有两个实体,一个是Book【书籍实体】,另外一个是出版商实体【Publisher】,一个出版商可以出版很多书籍,一本书只能是由一个出版商出版。所以,书籍和出版商之间是一对多的关系。

先来看看整个项目的结构吧:

 

Entity实体中:

BaseEntity实体:【日期使用了数据注解,这样在显示的时候,就有格式了。】

using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF.Entity{  public abstract class BaseEntity  {    /// <summary>    /// ID    /// </summary>    public int ID { get; set; }    /// <summary>    /// 添加时间    /// </summary>    ///     [DataType(DataType.Date)]    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]    public DateTime AddedDate { get; set; }    /// <summary>    /// 修改时间    /// </summary>    ///     [DataType(DataType.Date)]    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]    public DateTime ModifiedDate { get; set; }  }}

 

 Book实体:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF.Entity{  /// <summary>  /// Book实体  /// </summary>  public class Book:BaseEntity  {    /// <summary>    /// 书名    /// </summary>    public string BookName { get; set; }    /// <summary>    /// 书的作者    /// </summary>    public string BookAuthor { get; set; }    /// <summary>    /// 书的价格    /// </summary>    public decimal BookPrice { get; set; }    /// <summary>    /// 出版商编号    /// </summary>    public int PublisherId { get; set; }    /// <summary>    /// 导航属性---出版商    /// </summary>    public virtual Publisher Publisher { get; set; }  }}

 

出版商实体:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace EF.Entity{  public class Publisher:BaseEntity  {    /// <summary>    /// 出版商的名字    /// </summary>    public string PublisherName { get; set; }    /// <summary>    /// 导航属性    /// </summary>    public virtual ICollection<Book> Books { get; set; }  }}

 

然后在EF.Data项目中:

BookMap类:

using EF.Entity;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations.Schema;using System.Data.Entity.ModelConfiguration;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF.Data{  public class BookMap:EntityTypeConfiguration<Book>  {    public BookMap()    {      //配置主键      this.HasKey(s => s.ID);      //配置字段      this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);      this.Property(s => s.BookName).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();      // this.Property(s => s.BookAuthor).HasColumnType("nvarchar(50)").IsRequired();//注意这个和BookName字段配置的区别之处:这样写EF生成不了数据库      this.Property(s => s.BookAuthor).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();      this.Property(s => s.BookPrice).IsRequired();      this.Property(s => s.AddedDate).IsRequired();      this.Property(s => s.ModifiedDate).IsRequired();      this.Property(s => s.PublisherId).IsRequired();           //配置关系[一个出版商可以出版很多书籍]【外键单独配置,不是必须在Property中配置,当然也可以在Property中配置】      this.HasRequired(s => s.Publisher).WithMany(s => s.Books).HasForeignKey(s => s.PublisherId).WillCascadeOnDelete(true);      //配置表名字      this.ToTable("Books");          }  }}

PublisherMap类:

using EF.Entity;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations.Schema;using System.Data.Entity.ModelConfiguration;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF.Data{  public class PublisherMap:EntityTypeConfiguration<Publisher>  {    public PublisherMap()    {      //配置主键      this.HasKey(s => s.ID);      this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);     // this.Property(s => s.PublisherName).HasColumnType("nvarchar(50)").IsRequired();//这样写,有问题,生成不了数据库      this.Property(s => s.PublisherName).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();      this.Property(s => s.AddedDate).IsRequired();      this.Property(s => s.ModifiedDate).IsRequired();         }  }}

 

出版商我这里不做增删查改,到时候手动添加几条数据进去,然后在Book的视图中,把出版商做成下拉框的样式:所以我这里额外添加一个实体:【PublisherModel实体中的构造函数里的初始化属性嗲吗,不能忘记!!!】

using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Linq;using System.Web;using System.Web.Mvc;namespace EF.Web.Models{  public class PublisherModel  {    public PublisherModel()    {      PublisherList = new List<SelectListItem>();    }    [Display(Name="PublisherName")]    public int PublisherID { get; set; }    public List<SelectListItem> PublisherList { get; set; }  }}

 

数据上下文类:

using System;using System.Collections.Generic;using System.Data.Entity;using System.Data.Entity.ModelConfiguration;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace EF.Data{  public class EFDbContext:DbContext  {    public EFDbContext()      : base("name=DbConnectionString")    {        }    protected override void OnModelCreating(DbModelBuilder modelBuilder)    {      var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()    .Where(type => !String.IsNullOrEmpty(type.Namespace))    .Where(type => type.BaseType != null && type.BaseType.IsGenericType       && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));      foreach (var type in typesToRegister)      {        dynamic configurationInstance = Activator.CreateInstance(type);        modelBuilder.Configurations.Add(configurationInstance);      }       //base.OnModelCreating(modelBuilder);    }  }}

Ef.Data项目和Web项目中都要加上连接字符串:

<connectionStrings>  <add name="DbConnectionString" connectionString="Server=.;Database=EFCURDDB;uid=sa;Pwd=Password_1" providerName="System.Data.SqlClient"/> </connectionStrings>

 

现在看看Web项目:

using EF.Data;using EF.Entity;using EF.Web.Models;using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Web;using System.Web.Mvc;namespace EF.Web.Controllers{  public class BookController : Controller  {    private EFDbContext db;    public BookController()    {      db = new EFDbContext();    }    #region 列表    /// <summary>    /// 列表    /// </summary>    /// <returns></returns>    public ActionResult Index()    {      return View(db.Set<Book>().ToList());    }    #endregion    #region AddBook    /// <summary>    /// 添加Book    /// </summary>    /// <returns></returns>    public ActionResult AddBook()    {      PublisherModel model = new PublisherModel();      List<Publisher> listPublisher = db.Set<Publisher>().ToList();      foreach (var item in listPublisher)      {        model.PublisherList.Add(new SelectListItem()        {          Text = item.PublisherName,          Value = item.ID.ToString()        });      }      ViewBag.PublishedList = model.PublisherList;      return View();    }    /// <summary>    /// 添加Book    /// </summary>    /// <returns></returns>    [HttpPost]    public ActionResult AddBook([Bind(Include = "BookName,BookAuthor,BookPrice,AddedDate,ModifiedDate,PublisherId")] Book model)    {      Book addBook = new Book() {      AddedDate=model.AddedDate,      BookAuthor=model.BookAuthor,      BookName=model.BookName,      BookPrice=model.BookPrice,      ModifiedDate=model.ModifiedDate,      PublisherId = Convert.ToInt32( Request["PublishedName"].ToString())        //这里因为出版商我用的是另外的Model,视图中使用模型绑定只能用一个Model,所以修改和添加只能这样搞了。            };      db.Entry(addBook).State = EntityState.Added;      db.SaveChanges();      return RedirectToAction("Index");    }    #endregion    #region UpdateBook    /// <summary>    /// 修改Book    /// </summary>    /// <param name="bookId"></param>    /// <returns></returns>    public ActionResult UpdateBook(int bookId)    {      PublisherModel model = new PublisherModel();      List<Publisher> listPublisher = db.Set<Publisher>().ToList();      foreach (var item in listPublisher)      {        model.PublisherList.Add(new SelectListItem()        {          Text = item.PublisherName,          Value = item.ID.ToString()        });      }      ViewBag.PublishedList = model.PublisherList;      Book bookModel = db.Set<Book>().Where(s => s.ID == bookId).FirstOrDefault();      return View(bookModel);    }    /// <summary>    /// 修改Book    /// </summary>    /// <param name="model"></param>    /// <returns></returns>    [HttpPost]    public ActionResult UpdateBook([Bind(Include = "ID,BookName,BookAuthor,BookPrice,AddedDate,ModifiedDate,PublisherId")] Book model) //注意这里一定别忘记绑定 ID列哦    {      Book bookModel = db.Set<Book>().Where(s => s.ID == model.ID).FirstOrDefault();           if (bookModel != null)      {        Book updatemodel = new Book() {          AddedDate = model.AddedDate,          BookAuthor = model.BookAuthor,          ID = model.ID,          ModifiedDate = model.ModifiedDate,          BookName = model.BookName,          BookPrice = model.BookPrice,          PublisherId = Convert.ToInt32(Request["PublishedName"].ToString())//这里因为出版商我用的是另外的Model,视图中使用模型绑定只能用一个Model,所以修改和添加只能这样搞了。        };         db.Entry(bookModel).CurrentValues.SetValues(updatemodel); //保存的另外一种方式        db.SaveChanges();        return RedirectToAction("Index");      }      else      {        return View(model);      }      #region 保存的方式二      //db.Entry(model).State = EntityState.Modified;      //db.SaveChanges();      //return RedirectToAction("Index");       #endregion    }    #endregion    #region DeleteBook    public ActionResult DeleteBook(int bookId)    {      Book model = db.Set<Book>().Where(s => s.ID == bookId).FirstOrDefault();      return View(model);    }    [HttpPost]    public ActionResult DeleteBook(int bookId, FormCollection form)    {      Book model = db.Set<Book>().Where(s => s.ID == bookId).FirstOrDefault();      db.Entry(model).State = EntityState.Deleted;      db.SaveChanges();      return RedirectToAction("Index");    }    #endregion  }}

 

视图代码,我使用MVC模板生成:【适当做修改】

AddBook视图:

@model EF.Entity.Book@{  ViewBag.Title = "AddBook";}<h2>AddBook</h2>@using (Html.BeginForm("AddBook","Book",FormMethod.Post)) {  @Html.AntiForgeryToken()    <div class="form-horizontal">    <h4>Book</h4>    <hr />    @Html.ValidationSummary(true, "", new { @class = "text-danger" })    <div class="form-group">      @Html.LabelFor(model => model.AddedDate, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.AddedDate, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.AddedDate, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.ModifiedDate, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.ModifiedDate, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.ModifiedDate, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.BookName, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.BookName, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.BookName, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.BookAuthor, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.BookAuthor, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.BookAuthor, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.BookPrice, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.BookPrice, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.BookPrice, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.PublisherId, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.DropDownList("PublishedName", ViewData["PublishedList"] as List<SelectListItem>)        @*@Html.EditorFor(model => model.PublisherId, new { htmlAttributes = new { @class = "form-control" } })*@        @Html.ValidationMessageFor(model => model.PublisherId, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      <div class="col-md-offset-2 col-md-10">        <input type="submit" value="Create" class="btn btn-default" />      </div>    </div>  </div>}<div>  @Html.ActionLink("Back to List", "Index")</div><script src="~/Scripts/jquery-1.10.2.min.js"></script><script src="~/Scripts/jquery.validate.min.js"></script><script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

UpdateBook视图:

@model EF.Entity.Book@{  ViewBag.Title = "UpdateBook";}<h2>UpdateBook</h2>@using (Html.BeginForm("UpdateBook","Book",FormMethod.Post)){  @Html.AntiForgeryToken()    <div class="form-horizontal">    <h4>Book</h4>    <hr />    @Html.ValidationSummary(true, "", new { @class = "text-danger" })    @Html.HiddenFor(model => model.ID)    <div class="form-group">      @Html.LabelFor(model => model.AddedDate, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.AddedDate, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.AddedDate, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.ModifiedDate, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.ModifiedDate, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.ModifiedDate, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.BookName, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.BookName, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.BookName, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.BookAuthor, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.BookAuthor, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.BookAuthor, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.BookPrice, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.EditorFor(model => model.BookPrice, new { htmlAttributes = new { @class = "form-control" } })        @Html.ValidationMessageFor(model => model.BookPrice, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      @Html.LabelFor(model => model.PublisherId, htmlAttributes: new { @class = "control-label col-md-2" })      <div class="col-md-10">        @Html.DropDownList("PublishedName", ViewData["PublishedList"] as List<SelectListItem>)        @*@Html.EditorFor(model => model.PublisherId, new { htmlAttributes = new { @class = "form-control" } })*@        @Html.ValidationMessageFor(model => model.PublisherId, "", new { @class = "text-danger" })      </div>    </div>    <div class="form-group">      <div class="col-md-offset-2 col-md-10">        <input type="submit" value="Save" class="btn btn-default" />      </div>    </div>  </div>}<div>  @Html.ActionLink("Back to List", "Index")</div><script src="~/Scripts/jquery-1.10.2.min.js"></script><script src="~/Scripts/jquery.validate.min.js"></script><script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

注意:这里我只是把有改动的视图贴了出来,其他的视图,根据MVC模板生成之后,就不用管了。

@model IEnumerable<EF.Entity.Book>@{  ViewBag.Title = "Index";}<h2>Index</h2><p>  @Html.ActionLink("Create New", "AddBook")</p><table class="table">  <tr>    <th>      @Html.DisplayNameFor(model => model.AddedDate)    </th>    <th>      @Html.DisplayNameFor(model => model.ModifiedDate)    </th>    <th>      @Html.DisplayNameFor(model => model.BookName)    </th>    <th>      @Html.DisplayNameFor(model => model.BookAuthor)    </th>    <th>      @Html.DisplayNameFor(model => model.BookPrice)    </th>    <th>      @Html.DisplayNameFor(model => model.PublisherId)    </th>    <th></th>  </tr>@foreach (var item in Model) {  <tr>    <td>      @Html.DisplayFor(modelItem => item.AddedDate)    </td>    <td>      @Html.DisplayFor(modelItem => item.ModifiedDate)    </td>    <td>      @Html.DisplayFor(modelItem => item.BookName)    </td>    <td>      @Html.DisplayFor(modelItem => item.BookAuthor)    </td>    <td>      @Html.DisplayFor(modelItem => item.BookPrice)    </td>    <td>      @Html.DisplayFor(modelItem => item.PublisherId)    </td>    <td>      @Html.ActionLink("Edit", "UpdateBook", new { bookId = item.ID }) |      @Html.ActionLink("Details", "DetailsBook", new { bookId = item.ID }) |      @Html.ActionLink("Delete", "DeleteBook", new { bookId = item.ID })    </td>  </tr>}</table>

效果图:

 

 

 

 总结:1.下拉框实体中,构造函数初始化语句不能忘记。

2.修改的方式,有新变化看代码;

3.模型绑定的时候,特别要注意,Bind的字段,修改的时候,Bind字段ID不能少。