我们的示例数据库脚本:
USE [DB_USERS] GO /****** Object: Table [dbo].[Student] Script Date: 11/06/2015 00:01:52 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[Student]( [s_ID] [INT] IDENTITY(1,1) NOT NULL, [s_Name] [NVARCHAR](10) NULL, [s_Sex] [CHAR](2) NULL, [s_Age] [INT] NULL, [c_ID] [INT] NOT NULL, CONSTRAINT [PK__Studnet__2F3DA3BC267ABA7A] PRIMARY KEY CLUSTERED ( [s_ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [dbo].[Student] WITH CHECK ADD FOREIGN KEY([c_ID]) REFERENCES [dbo].[Classes] ([c_ID]) GO USE [DB_USERS] GO /****** Object: Table [dbo].[Classes] Script Date: 11/06/2015 00:02:15 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Classes]( [c_ID] [INT] NOT NULL, [c_Name] [NVARCHAR](50) NULL, PRIMARY KEY CLUSTERED ( [c_ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
然后新建MVC的项目:贴出框架图:
列表数据转成DTO的实例-">
后台的代码; 控制器的代码: using MVCAjax01.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCAjax01.Controllers { public class StudentController : Controller { ModelDB db = new ModelDB(); /// <summary> /// 生成学员列表页面 /// </summary> /// <returns></returns> public ActionResult Index() { return View(); } /// <summary> /// 根据页码加载数据 /// </summary> /// <param name="id">id参数其实传到页面中对应的pageIndex,那为什么用id,因为路由中是这么配置的</param> /// <returns></returns> public ActionResult List(int id) { int pageIndex = id; int pageSize = 3; //查询学员分页数据 //分页的步骤:orderby-->Skip((页码-1)*页容量)--->Take(页容量),最后tolist(). //List<Student> list = db.Students.OrderBy(s => s.s_ID).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); //换成DTO实体 //这样写就有问题了,db.Students的Students还是Model下面的EFstudent实体,这个时候可以这样改一下。 //List<MVCAjax01.Models.DTO.Student> list = db.Students.OrderBy(s => s.s_ID).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); //修正之后的(使用select方法映射一下,转成DTO,在里面要new一下每个DTO) //将EF查询出来的F实体集合转成DTO(data transfer object)实体集合 //List<MVCAjax01.Models.DTO.Student> list = db.Students.OrderBy(s => s.s_ID).Skip((pageIndex - 1) * pageSize).Take(pageSize).Select(s => new Models.DTO.Student() { //s_ID=s.s_ID, //s_Name=s.s_Name, //s_Age=s.s_Age, //s_Sex=s.s_Sex, //c_ID=s.c_ID, //Class=s.Class //}).ToList(); //TIPS:这里一个一个属性写太累了,我们可以写一个方法实体类转DTO的方法,在Model里添加一个类,写方法。 //在分布类中写了DTO转化方法之后,这边就不用select了。直接这样写。 //List<MVCAjax01.Models.DTO.Student> list = db.Students.OrderBy(s => s.s_ID).Skip((pageIndex - 1) * pageSize).Take(pageSize).Select( // s=>s.ToDto() //这样写还有个问题,就是Class属性刚才没有设置。这个时候还要做修改。 //).ToList(); //这个时候,可以这样修改, 但这样写还有问题,就是EF中的Class属性和DTO中的属性还是不一样,所以我们还是在DTO中做修改,同样我们需要为Class设置添加DTO类 //List<MVCAjax01.Models.DTO.Student> list = db.Students.OrderBy(s => s.s_ID).Skip((pageIndex - 1) * pageSize).Take(pageSize).Select( //s => { var sDTO = s.ToDto(); sDTO.Class = s.Class; return sDTO; } //将EF查出来的集合转成DTO实体集合,并返回(关于使用DTO类的时候注意,类名不要和EF实体类一样,不然会报错。) //然后,这边还有一个易错点:take方法之后必须要tolist,不然报错。 List<MVCAjax01.Models.DTO.StudentDTO> list = db.Students.OrderBy(s => s.s_ID).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList().Select( s =>s.ToDto() ).ToList(); //获取总行数(总数) int rowCount = db.Students.Count(); //计算总页数 int pageCount = Convert.ToInt32(Math.Ceiling((rowCount * 1.0) / pageSize)); //生成Json格式的数据(如果自己生成就很麻烦,这个时候就自己添加一个类,做法;我们在Model文件夹下添加一个类) #region 没有使用DTO的时候的版本 //没有使用DTO的时候的版本 ////操作:将数据封装到PagedDataModel 分页数据实体中 ////封装很简单啊,就是给属性赋值呗: ////弄成泛型类之后,要指定是哪个类 //PagedDataModel<Student> pageModel = new PagedDataModel<Student>() ////但不管怎么样,这个PagedDataModel实体中,仅仅是包含分页的数据相关的数据而已,那你转成Json格式的数据,你要把他转哇, ////发到浏览器去,浏览器肯定想知道,到底是成功还是没成功啊,状态是什么啊,所以我们还要准备一个类,这个时候就是JsonModel ////我们再在Model文件夹下添加一个JosnModel类 //{ // //data属性弄成泛型之后,这边就可以直接将list赋值给data了。 // Data = list, // PageCount = pageCount, // PageSize = pageSize, // RowCount = rowCount, // PageIndex = pageSize //}; #endregion #region 使用DTO之后的版本修改 //操作:将数据封装到PagedDataModel 分页数据实体中 //封装很简单啊,就是给属性赋值呗: //弄成泛型类之后,要指定是哪个类 PagedDataModel<Models.DTO.StudentDTO> pageModel = new PagedDataModel<Models.DTO.StudentDTO>() //但不管怎么样,这个PagedDataModel实体中,仅仅是包含分页的数据相关的数据而已,那你转成Json格式的数据,你要把他转哇, //发到浏览器去,浏览器肯定想知道,到底是成功还是没成功啊,状态是什么啊,所以我们还要准备一个类,这个时候就是JsonModel //我们再在Model文件夹下添加一个JosnModel类 { //data属性弄成泛型之后,这边就可以直接将list赋值给data了。 Data = list, PageCount = pageCount, PageSize = pageSize, RowCount = rowCount, PageIndex = pageSize }; //总结;上面的查询Student数据的时候,用EF查出来之后,转为了DTO的集合,(本来查出来的是EF的学员集合) #endregion //将分页数据实体,封装到json 标准格式实体中 JsonModel jsonModel = new JsonModel() { Data = pageModel, Message = "成功", Status = "OK" //BackUrl= 不给,没东西嘛! }; #region 这两行代码,相当于是json 方法 // System.Web.Script.Serialization.JavaScriptSerializer jsS = new System.Web.Script.Serialization.JavaScriptSerializer(); //string str= jsS.Serialize(list); #endregion //生成json格式的数据(通过json方法) //这个方法,内部其实就是帮我们调用JavaScriptSerializer的序列化方法,正是因为调用这个方法,所以我们在这里处理数据的时候,就会报错:循环引用。 //EF生成的实体类,只是方便查询的,真正使用的时候,特别做序列化的时候,还是要转成我们自己的实体类,这种实体类,我们把他叫做DTO,我们在Model文件夹下,新建一个文件夹DTO,然后在里面继续添加类。。 //备注: 拿到DTO集合之后,这边序列化的时候,就不会报错了。 //此json方法,默认只允许Post请求 return Json(jsonModel,JsonRequestBehavior.AllowGet); } } }
Index视图的代码:
@{ ViewBag.Title = "学员列表"; } @section headSection{ <script type="text/javascript"> $(function () { //关闭Jquery的浏览器缓存 //关闭缓存之后,每次都会发送一个数据到服务器获取数据 $.ajaxSetup({ cache: false }); //请求第一页数据 LoadPageList(1); }); //根据页码,异步请求数据 //我们读取页面的数据,是在服务端读取数据之后,直接生成HTML代码发过来,显示在表格里面好?还是在服务端拿到数据之后,先把数据转成Json,发到浏览器,然后浏览器根据json数据转化为HTML代码好? //Josn好,Json的传输量小一点。 //用json 的话就直接$.getJSON(),或者$.get() function LoadPageList(pageIndex) { //和getjson差不多,少了最后一个参数 //$.get("Student/List" + pageIndex, null, function (jsonData) { //}, "json"); //注意:get请求是不是使用浏览器缓存?那我们最好把浏览器缓存清除掉比较好。 //技巧哦,可以使用一个全局的变量,把缓存关掉 $.getJSON("Student/List" + pageIndex, null, function (jsonData) { alert(jsonData.msg); }); } </script> } <table id="tbList"> <tr> <th>ID</th> <th>Name</th> <th>Sex</th> <th>Age</th> <th>Class</th> <th>Operate</th> </tr> </table>
然后就是每个DTO文件夹下的两个类的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCAjax01.Models.DTO { /// <summary> /// DTO类的关键点是,我们自己写的类,而不是那个代理类,在用的时候,我们举找到查询的时候的代码,稍微修改一下 /// /// </summary> public class ClassDTO { //public Class() //{ // this.Students = new HashSet<Student>(); //} public int c_ID { get; set; } public string c_Name { get; set; } //同理这个属性也稍作修改,去掉virtual,其实班级里面,我们不知道有没有学员,要知道的话,可以去查,所以这个属性去掉,这里就注释吧 //public ICollection<Student> Students { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCAjax01.Models.DTO { ///DTO类的关键点是,我们自己写的类,而不是那个代理类,在用的时候,我们举找到查询的时候的代码,稍微修改一下 /// <summary> /// 这里面的实体,和EF中的Student实体一样,直接copy过来。 /// </summary> public class StudentDTO { public int s_ID { get; set; } public string s_Name { get; set; } public string s_Sex { get; set; } public Nullable<int> s_Age { get; set; } public int c_ID { get; set; } //只不过这个属性稍作修改 public ClassDTO Class { get; set; } } }
DTO转化的方法类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCAjax01.Models { /// <summary> /// 里面的名字要和EF一样,到时候合并为一个方法 /// </summary> public partial class Student { #region 1.0版本 先不设置Claa属性 //将EF Student实体,转成DTO学员实体 //1.0版本 先不设置Claa属性 //public DTO.Student ToDto() //{ // return new DTO.Student() // { // s_ID=this.s_ID, // c_ID=this.c_ID, // s_Sex=this.s_Sex, // //Class=this.Class, 这里不能直接写,但这里可以不给,class是外键,需要的时候,查询的时候给。现在回到控制器 // s_Age=this.s_Age, // s_Name=this.s_Name // }; #endregion #region 2.0 版本设置Class属性 public DTO.StudentDTO ToDto() { return new DTO.StudentDTO() { s_ID = this.s_ID, c_ID = this.c_ID, s_Sex = this.s_Sex, //Class=this.Class, 这里不能直接写,但这里可以不给,class是外键,需要的时候,查询的时候给。现在回到控制器 s_Age = this.s_Age, s_Name = this.s_Name, Class = this.Class.ToDto() }; #endregion } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCAjax01.Models { /// <summary> /// 里面的名字要和EF一样,到时候合并为一个方法 /// </summary> public partial class Class { public DTO.ClassDTO ToDto() { return new DTO.ClassDTO() { c_ID=this.c_ID, c_Name=this.c_Name }; } } }
分页数据实体类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCAjax01.Models { //里面要添加的属性,就是刚才计算的。 //写完之后,要序列化这个类。控制器中的操作: //操作:将数据封装到PagedDataModel 分页数据实体中 /// <summary> /// 分页数据实体 /// </summary> public class PagedDataModel<T> { /// <summary> /// 数据 /// </summary> public List<T> Data { get; set; } //这个data属性,应该用object类型,当然也可以使用泛型,具体:把类写作泛型类,返回data属性弄成泛型 /// <summary> /// 页码(在这里可以设置或者不设置) /// </summary> public int PageIndex { get; set; } /// <summary> /// 页容量(在这里可以设置或者不设置) /// </summary> public int PageSize { get; set; } /// <summary> /// 总页数 /// </summary> public int PageCount { get; set; } /// <summary> /// 总行数(总数) /// </summary> public int RowCount { get; set; } } }
JsonModel实体类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCAjax01.Models { /// <summary> /// Json数据实体 /// </summary> public class JsonModel { public object Data { get; set; } public string Message { get; set; } public string Status { get; set; } public string BackUrl { get; set; } } }
最后附上几幅图:
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索数据
, 浏览器
, 代码
, this
, 属性
using
,以便于您获取更多的相关知识。
时间: 2024-10-25 11:31:45