码迷,mamicode.com
首页 > Web开发 > 详细

使用Ajax请求MVC查出的EF转成DTO的数据?

时间:2015-11-06 01:39:20      阅读:535      评论:0      收藏:0      [点我收藏+]

标签:

背景:想要使用Ajax来获取列表数据:

记笔记模式开始:

首先数据库脚本:

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的项目:我先把框架图贴出来:

技术分享

然后贴出后台的代码;

控制器的代码:

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>
View Code

 

然后就是每个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; }
    }
}

最后附上几幅图:

技术分享

技术分享技术分享技术分享

使用Ajax请求MVC查出的EF转成DTO的数据?

标签:

原文地址:http://www.cnblogs.com/caofangsheng/p/4941299.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!