3、ASP.NET MVC入门到精通——Entity Framework增删改查

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03



这里我接上讲Entity Framework入门。从网上下载Northwind数据库,新建一个控制台程序,然后重新添加一个ado.net实体数据模型。

EF中操作数据库的"网关"(操作上下文)

DBContext封装 .NET Framework 和数据库之间的连接。此类用作“创建”、“读取”、“更新”和“删除”操作的网关。
DBContext 类为主类,用于与作为对象(这些对象为 EDM 中定义的实体类型的实例)的数据进行交互。
DBContext 类的实例封装以下内容:

  • 到数据库的连接,以 EntityConnection 对象的形式封装。
  • 描述该模型的元数据,以 MetadataWorkspace 对象的形式封装
  • 用于管理缓存中持久保存的对象的 ObjectStateManager 对象

一、新增

        #region 新增 1.0
        static int Add()
        {
            Customers _Customers = new Customers {CustomerID="zhang",Address="洛阳西街",City="洛阳",Phone="1314520",            CompanyName="微软",ContactName="李四" };
            //方法一
            //db.Customers.Add(_Customers);

            //方法二
            DbEntityEntry<Customers> entry = db.Entry<Customers>(_Customers);
            entry.State = System.Data.Entity.EntityState.Added;

           return db.SaveChanges();
        }
        #endregion

二、简单查询 延时加载

为了查看延时加载,要使用SqlProfiler跟踪sql语句

EF生成sql语句发送给数据库执行,我们可以使用sqlserver的跟踪监测工具查看。(可监测sql语句、CPU占用、执行时间等)

【延时加载】 看成两种:

1、 EF本身查询方法 返回的都是 IQueryable接口,此时并未查询数据库;只有当调用接口方法 获取 数据时,才会查询数据库

2、 【延时加载】,本质原因之一:当前可能通过多个SQO方法 来组合 查询条件,那么每个方法 都只是添加一个查询条件而已,无法确定本次查询条件 是否 已经添加结束  所以,没有办法在每个SQO方法的时候确定SQL语句是什么,只能返回一个 包含了所有添加的条件的 DBQuery 对象,  当使用这个 DBQuery对象 的时候,才根据所有条件 生成 sql语句,查询数据库

        #region 2.1 简单查询 延迟加载 -void QueryDelay_01()
        static void QueryDelay_01()
        {
            DbQuery<Customers> dbQuery = db.Customers.Where(u => u.ContactName == "张学友").OrderBy(u => u.ContactName).Take(2) 

as System.Data.Entity.Infrastructure.DbQuery<Customers>;
            //获得 延迟查询对象后,调用对象的 获取第一个数据方法,此时,【就会根据之前的条件】,生成sql语句,查询数据库了~~!
            Customers usr01 = dbQuery.FirstOrDefault();// ToList()......
            Console.WriteLine(usr01.ContactName);
        }

        //2.1.2【延迟加载】- 针对于 外键实体 的延迟(按需加载)!
        //                  本质原因之二:对于外键属性而言,EF会在用到这个外键属性的时候才去查询 对应的 表。
        static void QueryDelay_02()
        {
            IQueryable<Orders> _Orders = db.Orders.Where(a => a.CustomerID == "TOMSP");//真实返回的 DbQuery 对象,以接口方式返回
            //a.此时只查询了 地址表
            Orders order = _Orders.FirstOrDefault();
            //b.当访问 地址对象 里的 外键实体时,EF会查询 地址对应 的用户表;查询到之后,将数据 装入 这个外键实体
            Console.WriteLine(order.Customers.ContactName);

            //c.【延迟加载】按需加载 的缺点:每次调用外键实体时,都会去查询数据库(EF有小优化:相同的外键实体只查一次)
            IQueryable<Orders> orderList = db.Orders;
            foreach (Orders o in orderList)
            {
                Console.WriteLine(o.OrderID + ":ContactName=" + o.Customers.ContactName);
            }
        }
        #endregion
        #region 2.2 根据条件 排序 和查询 + List<Customers> GetListBy<TKey>
        /// <summary>
        /// 2.2 根据条件 排序 和查询
        /// </summary>
        /// <typeparam name="TKey">排序字段类型</typeparam>
        /// <param name="whereLambda">查询条件 lambda表达式</param>
        /// <param name="orderLambda">排序条件 lambda表达式</param>
        /// <returns></returns>
        public List<Customers> GetListBy<TKey>(Expression<Func<Customers, bool>> whereLambda, Expression<Func<Customers, TKey>> orderLambda)
        {
            return db.Customers.Where(whereLambda).OrderBy(orderLambda).ToList();
        }
        #endregion

        #region 2.3 分页查询 + List<P05MODEL.User> GetPagedList<TKey>
        /// <summary>
        /// 2.3 分页查询 + List<Customers> GetPagedList<TKey>
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <param name="whereLambda">条件 lambda表达式</param>
        /// <param name="orderBy">排序 lambda表达式</param>
        /// <returns></returns>
        public List<Customers> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<Customers, bool>> whereLambda, Expression<Func<Customers, TKey>> orderBy)
        {
            // 分页 一定注意: Skip 之前一定要 OrderBy
            return db.Customers.Where(whereLambda).OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
        }
        #endregion

三、修改

        #region 3.0 官方推荐的 修改方式(先查询,再修改)
        /// <summary>
        /// 3.0 官方推荐的 修改方式(先查询,再修改)
        /// </summary>
        static void Edit()
        {
            //1.查询出一个 要修改的对象 -- 注意:此时返回的 是 一个 Customers类的 代理类对象(包装类对象)
            Customers _Customers = db.Customers.Where(u => u.CustomerID == "zhang").FirstOrDefault();
            Console.WriteLine("修改前:" + _Customers.ContactName);
            //2.修改内容 -- 注意:此时其实操作的 是 代理类对象 的属性,这些属性,会将值设置给内部的 Customers对象对应的属性,同时标记此属性为已修改状态
            _Customers.ContactName = "刘德华";
            //3.重新保存到数据库 -- 注意:此时 ef上下文,会检查容器内部 所有的对象,找到标记为修改的对象,然后找到标记为修改的对象属性,生成对应的update语句执行!
            db.SaveChanges();
            Console.WriteLine("修改成功:");
            Console.WriteLine(_Customers.ContactName);
        }
        #endregion

        #region 3.1 自己优化的 修改方式(创建对象,直接修改)
        /// <summary>
        /// 3.1 自己优化的 修改方式(创建对象,直接修改)
        /// </summary>
        static void Edit2()
        {
            //1.查询出一个 要修改的对象
            Customers _Customers = new Customers() { CustomerID = "zhang", Address = "洛阳西街", City = "洛阳", Phone = "1314520", CompanyName = "微软", ContactName = "张学友" };
            //2.将 对象 加入 EF容器,并获取 当前实体对象 的 状态管理对象
            DbEntityEntry<Customers> entry = db.Entry<Customers>(_Customers);
            //3.设置 该对象 为被修改过
            entry.State = System.Data.EntityState.Unchanged;
            //4.设置 该对象 的 ContactName属性 为 修改状态,同时 entry.State 被修改为 Modified 状态
            entry.Property("ContactName").IsModified = true;

            //var u = db.Customers.Attach(_Customers);
            //u.ContactName = "郭富城";

            //3.重新保存到数据库 -- ef 上下文 会 根据 实体对象的 状态 ,根据 entry.State =Modified 的值 生成 对应的 update sql 语句
            db.SaveChanges();
            Console.WriteLine("修改成功:");
            Console.WriteLine(_Customers.ContactName);
        }
        #endregion

四、删除

        #region 4.0 删除 -void Delete()
        /// <summary>
        /// 4.0 删除
        /// </summary>
        static void Delete()
        {
            //4.1创建要删除的 对象
            Customers u = new Customers() { CustomerID = "zhang" };
            //4.2附加到 EF中
            db.Customers.Attach(u);
            //4.3标记为删除 注意:此方法 就是 起到了 标记 当前对象  为 删除状态 !
            db.Customers.Remove(u);

            /*
                也可以使用 Entry 来附加和 修改
                DbEntityEntry<Customers> entry = db.Entry<Customers>(u);
                entry.State = System.Data.EntityState.Deleted;
             */

            //4.4执行删除sql
            db.SaveChanges();
            Console.WriteLine("删除成功~~~");
        }
        #endregion

五、批处理

        #region 5.0 批处理 -- 上下文 SaveChanges 方法 的 好处!!!!
        /// <summary>
        /// 批处理 -- 上下文 SaveChanges 方法 的 好处!!!!
        /// </summary>
        static void SaveBatched()
        {
            //5.1新增数据
            Customers _Customers = new Customers { CustomerID = "zou", Address = "洛阳西街", City = "洛阳", Phone = "1314520", CompanyName = "微软", ContactName = "邹玉杰" };
            db.Customers.Add(_Customers);

            //5.2新增第二个数据
            Customers _Customers2 = new Customers { CustomerID = "zhao", Address = "洛阳西街", City = "洛阳", Phone = "1314520", CompanyName = "微软", ContactName = "赵匡胤" };
            db.Customers.Add(_Customers2);

            //5.3修改数据
            Customers usr = new Customers() { CustomerID = "zhao", ContactName = "赵牧" };
            DbEntityEntry<Customers> entry = db.Entry<Customers>(usr);
            entry.State = System.Data.EntityState.Unchanged;
            entry.Property("ContactName").IsModified = true;

            //5.4删除数据
            Customers u = new Customers() { CustomerID = "zou" };
            //4.2附加到 EF中
            db.Customers.Attach(u);
            //4.3标记为删除 注意:此方法 就是 起到了 标记 当前对象  为 删除状态 !
            db.Customers.Remove(u);

            db.SaveChanges();
            Console.WriteLine("批处理 完成~~~~~~~~~~~~!");
        }
        #endregion

        #region 5.1 批处理 -- 一次新增 50条数据 -void BatcheAdd()
        /// <summary>
        /// 5.1 批处理 -- 一次新增 50条数据
        /// </summary>
        static void BatcheAdd()
        {
            for (int i = 0; i < 50; i++)
            {
                Customers _Customers = new Customers { CustomerID = "zou" + i, Address = "洛阳西街", City = "洛阳", Phone = "1314520", CompanyName = "微软", ContactName = "邹玉杰" + i };
                db.Customers.Add(_Customers);
            }
            db.SaveChanges();
        }
        #endregion

通用数据库操作基类

我们看到这些数据库基本操作CRUD等,可以通过泛型提取出来放到父类里面,不需要每个不同的数据库操作类中都写一遍。

    public class BaseDAL<T> where T:class,new()
    {
        /// <summary>
        /// 数据上下文对象
        /// </summary>
        P05MODEL.LeaveWordBoradEntities db = new P05MODEL.LeaveWordBoradEntities();

        #region 1.0 新增 实体 +int Add(T model)
        /// <summary>
        /// 新增 实体
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public int Add(T model)
        {
            db.Set<T>().Add(model);
            return db.SaveChanges();//保存成功后,会将自增的id设置给 model的 主键属性,并返回受影响行数
        }
        #endregion

        #region 2.0 根据 id 删除 +int Del(T model)
        /// <summary>
        /// 根据 id 删除
        /// </summary>
        /// <param name="model">包含要删除id的对象</param>
        /// <returns></returns>
        public int Del(T model)
        {
            db.Set<T>().Attach(model);
            db.Set<T>().Remove(model);
            return db.SaveChanges();
        }
        #endregion

        #region 3.0 根据条件删除 +int DelBy(Expression<Func<T, bool>> delWhere)
        /// <summary>
        /// 3.0 根据条件删除
        /// </summary>
        /// <param name="delWhere"></param>
        /// <returns></returns>
        public int DelBy(Expression<Func<T, bool>> delWhere)
        {
            //3.1查询要删除的数据
            List<T> listDeleting = db.Set<T>().Where(delWhere).ToList();
            //3.2将要删除的数据 用删除方法添加到 EF 容器中
            listDeleting.ForEach(u =>
            {
                db.Set<T>().Attach(u);//先附加到 EF容器
                db.Set<T>().Remove(u);//标识为 删除 状态
            });
            //3.3一次性 生成sql语句到数据库执行删除
            return db.SaveChanges();
        }
        #endregion

        #region 4.0 修改 +int Modify(T model, params string[] proNames)
        /// <summary>
        /// 4.0 修改,如:
        /// T u = new T() { uId = 1, uLoginName = "asdfasdf" };
        /// this.Modify(u, "uLoginName");
        /// </summary>
        /// <param name="model">要修改的实体对象</param>
        /// <param name="proNames">要修改的 属性 名称</param>
        /// <returns></returns>
        public int Modify(T model, params string[] proNames)
        {
            //4.1将 对象 添加到 EF中
            DbEntityEntry entry = db.Entry<T>(model);
            //4.2先设置 对象的包装 状态为 Unchanged
            entry.State = System.Data.EntityState.Unchanged;
            //4.3循环 被修改的属性名 数组
            foreach (string proName in proNames)
            {
                //4.4将每个 被修改的属性的状态 设置为已修改状态;后面生成update语句时,就只为已修改的属性 更新
                entry.Property(proName).IsModified = true;
            }
            //4.4一次性 生成sql语句到数据库执行
            return db.SaveChanges();
        }
        #endregion

        #region 4.0 批量修改 +int Modify(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
        /// <summary>
        /// 4.0 批量修改
        /// </summary>
        /// <param name="model">要修改的实体对象</param>
        /// <param name="whereLambda">查询条件</param>
        /// <param name="proNames">要修改的 属性 名称</param>
        /// <returns></returns>
        public int ModifyBy(T model, Expression<Func<T, bool>> whereLambda, params string[] modifiedProNames)
        {
            //4.1查询要修改的数据
            List<T> listModifing = db.Set<T>().Where(whereLambda).ToList();

            //获取 实体类 类型对象
            Type t = typeof(T); // model.GetType();
            //获取 实体类 所有的 公有属性
            List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            //创建 实体属性 字典集合
            Dictionary<string, PropertyInfo> dictPros = new Dictionary<string, PropertyInfo>();
            //将 实体属性 中要修改的属性名 添加到 字典集合中 键:属性名  值:属性对象
            proInfos.ForEach(p =>
            {
                if (modifiedProNames.Contains(p.Name))
                {
                    dictPros.Add(p.Name, p);
                }
            });

            //4.3循环 要修改的属性名
            foreach (string proName in modifiedProNames)
            {
                //判断 要修改的属性名是否在 实体类的属性集合中存在
                if (dictPros.ContainsKey(proName))
                {
                    //如果存在,则取出要修改的 属性对象
                    PropertyInfo proInfo = dictPros[proName];
                    //取出 要修改的值
                    object newValue = proInfo.GetValue(model, null); //object newValue = model.uName;

                    //4.4批量设置 要修改 对象的 属性
                    foreach (T usrO in listModifing)
                    {
                        //为 要修改的对象 的 要修改的属性 设置新的值
                        proInfo.SetValue(usrO, newValue, null); //usrO.uName = newValue;
                    }
                }
            }
            //4.4一次性 生成sql语句到数据库执行
            return db.SaveChanges();
        }
        #endregion

        #region 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda)
        /// <summary>
        /// 5.0 根据条件查询 +List<T> GetListBy(Expression<Func<T,bool>> whereLambda)
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <returns></returns>
        public List<T> GetListBy(Expression<Func<T, bool>> whereLambda)
        {
            return db.Set<T>().Where(whereLambda).ToList();
        }
        #endregion

        #region 5.1 根据条件 排序 和查询 + List<T> GetListBy<TKey>
        /// <summary>
        /// 5.1 根据条件 排序 和查询
        /// </summary>
        /// <typeparam name="TKey">排序字段类型</typeparam>
        /// <param name="whereLambda">查询条件 lambda表达式</param>
        /// <param name="orderLambda">排序条件 lambda表达式</param>
        /// <returns></returns>
        public List<T> GetListBy<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderLambda)
        {
            return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).ToList();
        }
        #endregion

        #region 6.0 分页查询 + List<T> GetPagedList<TKey>
        /// <summary>
        /// 6.0 分页查询 + List<T> GetPagedList<TKey>
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <param name="whereLambda">条件 lambda表达式</param>
        /// <param name="orderBy">排序 lambda表达式</param>
        /// <returns></returns>
        public List<T> GetPagedList<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy)
        {
            // 分页 一定注意: Skip 之前一定要 OrderBy
            return db.Set<T>().Where(whereLambda).OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
        }
        #endregion
    }

参考页面:http://qingqingquege.cnblogs.com/p/5933752.html

时间: 2024-12-18 17:42:36

3、ASP.NET MVC入门到精通——Entity Framework增删改查的相关文章

【C#】Entity Framework 增删改查和事务操作

1.增加对象 DbEntity db = new DbEntity(); //创建对象实体,注意,这里需要对所有属性进行赋值(除了自动增长主键外),如果不赋值,则会数据库中会被设置为NULL(注意是否可空) var user = new User { Name = "bomo", Age = 21, Gender = "male" }; db.User.Add(user); db.SaveChanges(); 2.删除对象,删除只需要对象的主键 DbEntity d

【转载】ASP.NET MVC Web API 学习笔记---联系人增删改查

本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系人 说明:为了方便数据不使用真正的数据库,而是通过内存数据模拟 1.       Web API中包含的方法 Action HTTP method Relative URI GetAllContact GET /api/contact GetContact GET /api/contact /id

Entity Framework增删改查

这里我接上讲Entity Framework入门.从网上下载Northwind数据库,新建一个控制台程序,然后重新添加一个ado.net实体数据模型. EF中操作数据库的"网关"(操作上下文) DBContext封装 .NET Framework 和数据库之间的连接.此类用作“创建”.“读取”.“更新”和“删除”操作的网关.DBContext 类为主类,用于与作为对象(这些对象为 EDM 中定义的实体类型的实例)的数据进行交互.DBContext 类的实例封装以下内容: 到数据库的连接

ASP.NET MVC之Entity Framework增删改查

一.EntityFramework简介 ORM(Object-Relation-Mapping):对象关系映射,主要实现基于面向对象方式操作数据库的各种方法,是一种框架技术.长期以来,C#OOP和数据库操作一直处于分离状态.C#最后的操作都要转换成普通的SQL语句,从开发角度来讲,这种转换工作,对于快速开发来讲,效率会有一定影响.ORM出来以后:这种转换工作,其实由ORM框架本身完成.完成基于对象操作数据. .NET中的ORM框架:.NHibernate.MyBatis.NET.LINQ to

Entity Framework 增删改查和事务操作

1.增加对象 复制代码 DbEntity db = new DbEntity(); //创建对象实体,注意,这里需要对所有属性进行赋值(除了自动增长主键外),如果不赋值,则会数据库中会被设置为NULL(注意是否可空) var user = new User { Name = "bomo", Age = 21, Gender = "male" }; db.User.Add(user); db.SaveChanges(); 复制代码 2.删除对象,删除只需要对象的主键

浅谈Entity Framework 增删改查和事务操作

1.增加对象 DbEntity db = new DbEntity(); //创建对象实体,注意,这里需要对所有属性进行赋值(除了自动增长主键外),如果不赋值,则会数据库中会被设置为NULL(注意是否可空) var user = new User { Name = "bomo", Age = 21, Gender = "male" }; db.User.Add(user); db.SaveChanges(); 2.删除对象,删除只需要对象的主键 DbEntity d

26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做准备,由于许久没有练习双截棍了,难免生疏,所以现在临时抱佛脚.深圳最近的天气反常,许多人感冒了,我也成为其中之一,大家注意身体... 这一篇,我来简单的讲一下接下来项目中会用到的一些杂七杂八的技术. 区域及分离 在15.ASP.NET MVC入门到精通——MVC-路由中,我已经简要说明了区域的分离. 1.右键单击Web项目,“添加”——“区域”,区域名,

22、ASP.NET MVC入门到精通——搭建项目框架

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 前面的章节,说了ASP.NET MVC项目中常用的一些技术和知识点,更多的是理论上面的东西,接下来,我将通过一个简单的OA项目来应用我们之前涉及到的一些技术,为了兼顾初学者,所以我尽量把操作步骤说得足够详细.(本来想用VS2015来演示MVC5开发的,无奈家里的笔记本是11年2月份的老爷机了,一直未曾舍得换,因为配置的缘故,笔记本不堪负重,难以安装最新版本的开发工具,只装了VS2012,当然,还有一个原因就是现在公司也是使用VS2012

ASP.NET MVC入门到精通——14.MVC请求管道

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 ASP.NET MVC的请求管道和ASP.NET请求管道基本上一模一样,如果你对ASP.NET请求管道十分熟悉的话,你只要关注一下不同点.看懂下面两张图,你就基本上明了了,不明天的地方,用reflector工具查看MVC的源码,没其它的..NET框架的源码里面几乎涉猎了各种设计模式.这一节的内容,我也不知道怎么说,都在图里面了,看图比直接用文字说明要明了得多,比较这些东西还是比较抽象的,如果你时间充裕,建议看下MVC的源码.怎么看?就找