那么现在我们已经大概从本质上了解了ef

巴拉巴拉说了一大堆之后
总算要进入ef的正题了

总在口头说也太不行了是吧~
没错,现在要用ef进行一些实际的操作

做什么呢?

就做一个入门级的增删改查操作吧

废话不说,开搞~



首先

操作的数据库还是之前建立的例子

关系图:



已经是我们的老朋友啦

简单又好用~



还是建立一个控制台应用程序

根据数据库生成ADO.NET实体数据模型





准备工作做完之后

现在可以放开那个鼠标

放手敲代码吧~



使用EF最最开始要做什么事情?

准备一个EF上下文对象

因为EF的所有操作都要通过这个上下文对象来完成

之前我们说过



这个Model.Context.cs文件就是EF的上下文

后缀名是cs的是什么文件

是不是有一种似曾相识的赶脚?

不就是C#中的类嘛!

双击点开它瞧瞧



是不是一个很标准的名字叫做Entities的类?

其中包含了两个类型为DbSet集合的属性,分别是T_Products和T_Users

是不是又很熟悉

没错

这就是上下文对象中保存的

对应数据库表的属性

我们可以直接通过这个Entities.属性的方式方便快速的操作数据库

爽吧?

具体怎么爽

马上你就知道~



实例化一个Entities上下文对象





那么现在我们来想一想

使用ADO.NET进行新增操作的时候需要做什么?

无非就是new一个实体类对象,为该对象的各个属性赋值

在根据这么属性的值来生成sql语句发送到数据库



这种思路也通用于EF

但是更加简便

不信?

上证据:

//首先new一个T_Users对象,并为其UserName属性赋值
T_Users user = new T_Users() { UserName = "JChubby" };

然后使用之前实例化的EF上下文对象,找到T_Users属性,在点一下,是不是有一个很显眼的Add方法?



再看看这个Add方法的参数



是不是很明显的一个T_Users实体对象!

没错,不要怀疑了,就是它了

将之前new的实体对象传给Add方法

然后调用一下dbEntities的SaveChanges方法

注意,EF非查询操作只有在调用了这个方法之后才会向数据库发送请求!

这是一个很重要的方法,以后我们会详细的针对它展开讨论

现在暂时放过它吧~



整个新增方法如下:

private static void Create()
{
T_Users user = new T_Users() { UserName = "JChubby" };
dbEntities.T_Users.Add(user);
dbEntities.SaveChanges();
Console.WriteLine("添加成功!");
}

没了

没了?!

怎么就没了?

这才几行代码

放心吧~

不骗你

不行走一个试试~

在Main方法中调用Create方法,运行



你还不确定的话回头去看数据库

没有这个数据你来找我~



那么此时你就会觉得EF很简单

因为有新增的方法肯定会有删除啊,修改啊之类的方法,到时候直接调不就行了~

先别着急下定论~

一是一横,二是两个横,三是三个横,难道四就是四个横吗?

很明显不是



先来看看Delete删除方法

EF中实现删除有两种方式

版本一:

//实例化一个T_Users对象,并指定Id的值
T_Users user = new T_Users() { Id = 1 };
//将user附加到上下文对象中,并获得EF容器的管理对象
var entry = dbEntities.Entry(user);
//设置该对象的状态为删除
entry.State = EntityState.Deleted;
//保存修改
dbEntities.SaveChanges();
Console.WriteLine("删除成功!");

这个应该可以理解的吧,虽然思路有点奇葩



版本二:

private static void Delete()
{
//实例化一个T_Users对象,并指定Id的值
T_Users user = new T_Users() { Id = 1 };
//将user附加到上下文对象中
dbEntities.T_Users.Attach(user);
//删除user对象
dbEntities.T_Users.Remove(user);
//保存修改
dbEntities.SaveChanges();
Console.WriteLine("删除成功!");
}

这不是有一个Remove吗,一看就知道是删除用的呀

但是这个Attach是什么鬼东西?

直接删除不就好了

干嘛还要附加,然后在删除

这不是闲着蛋疼吗?

Attach是真的附加方法

但是Remove就不是真的删除方法了

没证据我会乱说?

我们在Attach方法之后加一句代码

var entry = dbEntities.Entry(user);

作用是方便看清楚entry变量的State属性,也就是user实体的状态信息

在Remove和SaveChanges方法分别设上断点,运行进行调试

程序执行完Attach之后在Remove停下



注意看下面的监视区域

user实体的状态信息为Unchanged

从字面上的意思来理解就是没有改变的

那么接着运行,执行Remove方法,停在SaveChanges



看到那个大红的Deleted了吗?

这就证明了

Remove方法并不是将实体从数据库中删除

只是将实体的State属性设置成Deleted

在上下文对象调用SaveChanges方法的时候

它一看到这个实体的State是Deleted

那么它就会向数据库发送删除的请求

其实第二个版本本质上还是继续这第一个版本的操作

只是简便了一些



至于查询方法

那就更爽了

怎么爽?

听说过Lambda吗?

没有?

那你就out了!

真的,赶紧去冲一下电,不骗你

因为在EF中使用Lambda真的是太爽了(当然也可以用Linq,这也很爽!)

怎么爽?

看看下面的代码你就知道了

private static void Query()
{
//取出数据库T_Users表中所有的数据,并转成集合
List<T_Users> users = dbEntities.T_Users.Where(u => true).ToList();
//循环遍历输出所有的user实体的UserName属性
users.ForEach(u => Console.WriteLine(u.UserName));
}

好了,批量查询搞定

就两行代码~

这里需要注意的是

Where方法的参数是一个Lambda表达式,并且返回的是IQueryable的泛型接口

所以如果只是查询一条数据,记得用FirstOrDefault方法,只返回一条数据

但是在这里又牵扯到了前面我们所说过的EF的延迟加载功能

详细介绍实在太长~

想了解的同志们小手一抖,轻轻带走EF延迟加载的本质原因



除了牵扯到延迟加载

还涉及到一个小问题

现在我们将代码改为只查询单个数据

var user = dbEntities.T_Users.Where(u => u.Id == 3).FirstOrDefault();
Console.WriteLine(user.UserName);

在Console.WriteLine设置断点,运行

将user对象添加监视

注意看监视栏



是不是很惊悚?!

user的类型怎么变成System.Data.Entity.DynamicProxies.T_Users_185D30475F9AA2490A...

什么乱七八糟的东西

不是T_Users类型的对象吗?

终于找到为什么使用返回来的实体对象序列化成json格式

返回前台老是报错的原因了

因为人家根本就不是T_Users类啊!

完全两个不同的类型!



其实这是一个EF的动态代理类

那么这个动态代理类是什么飞机?

因为这里又涉及到了后面的修改等操作

所以这个动态代理类放在后面修改方法的地方在详细说明







最后我们来看看修改的方法

微软官方推荐的做法是先查询,后修改

就是先把要修改的数据查出来,然后修改完成之后再保存到数据库

具体操作如下:

private static void Modify()
{
//将Id为2的T_Users数据取出
var user = dbEntities.T_Users.Where(u => u.Id == 2).FirstOrDefault();
Console.WriteLine("修改之前:" + user.UserName);
//修改UserName属性
user.UserName = "222222222222222";
//保存修改
dbEntities.SaveChanges();
Console.WriteLine("修改之后:" + user.UserName);
}

这么做虽然也是挺方便的吧

但是总是觉得怪怪的

因为我们一般做修改的时候直接实例化对象穿进去,然后在根据Id修改对应数据的值

没用过先查询后修改的法子呀

接下来看看按照我们平常思路的修改方法

//实例化user对象
T_Users user = new T_Users() {Id = 1, UserName = "2222"};
//将user加入EF容器中,并获得EF容器的管理对象
var entry = dbEntities.Entry(user);
//设置对象的状态为Unchanged
entry.State = EntityState.Unchanged;
//设置要修改的属性的IsModified=true,表示这个属性是要修改的
entry.Property("UserName").IsModified = true;
//保存
dbEntities.SaveChanges();

但是现在又觉得奇怪了

为什么要先设置对象的状态为Unchanged

然后在设置要修改的属性的IsModified=true

这好像又多此一举了?

EF修改数据的时候有一个特点

它会根据要修改的属性生成update语句

而不是将每个属性都加入到update语句中

譬如版本一的修改

我们只对UserName属性做了修改

那么最后生成的update语句也只会有UserName

想想看当一个表中字段有n多个时

但是我们只需要修改一个字段的值

那么update语句是写上全部的属性好

还是只写要修改的字段好?

答案不是很明显嘛!

使用版本一方法进行修改时

EF只生成有赋值过的属性

而在版本二中

我们同样希望能够使用EF的这个特性进行sql语句的优化

但是如果直接这么做的话

var entry = dbEntities.Entry(user);
entry.State = EntityState.Modified;

想都不用想肯定是生成所有的属性

所以我们需要先把实体的State设置为Unchanged

然后为要修改的属性

一一将它们的IsModified设置为true

什么意思很明显了吧?

两个修改版本最后的效果是一样的

怎么选择看个人爱好了~

那么是不是觉得EF的这个优化挺不错的?

但是我们修改user对象的哪个属性EF上下文是怎么知道的?

难道它时时刻刻都在监控user对象的信息吗?

这显然是不太可能的

它完成这个工作是靠着一个动态代理类来实现的

没错

就是前面查询操作提到的那货

下面给出一张图来解释



额...画的很难看

意思也表达的不是很全面

如果看不懂的同志

老方法

google之~





好了,简单的增删改查

get it!

期待明天的行程

一路走过来

总是需要记录一些风景

待人老了花谢了

我们还有记忆可以回忆~

那么今天记录就到此结束~














ASP.NET MVC学习---(三)EF简单增删改查的更多相关文章

  1. MVC学习-用EF做增删改查

    在做增删改查先,先介绍几个知识点: 1.代理类 在将对象方法EF数据上下文时,EF会为该对象封装 一个代理类对象, 同时为该对象的每一个属性添加一个标志:unchanged, 当对该对象某个属性进行操 ...

  2. ado.net的简单数据库操作(三)——简单增删改查的实际应用

    果然,在犯困的时候就该写写博客,写博客就不困了,哈哈! 上篇我记录了自己的SqlHelper的开发过程,今天记录一下如何使用这个sqlhelper书写一个具有简单增删改查的小实例啦. 实例描述:在数据 ...

  3. [EF]使用EF简单增删改查

    目录 认识EF 添加数据 删除数据 修改数据 查询数据 总结 认识EF ADO.NET Entity Framework 是微软以ADO.NET为基础所发展出来的对象关系对伊(O/R Mapping) ...

  4. 【EF学习笔记04】----------EF简单增删改查

    第一步:创建上下文对象 using(var db = new Entities()) { //数据操作 } 新增 UserInfo user = new UserInfo() { UserName = ...

  5. EF简单增删改查

    第一步:创建上下文对象 using(var db = new Entities()) { //数据操作 } 新增 UserInfo user = new UserInfo() { UserName = ...

  6. asp.net mvc中用angularJs写的增删改查的demo。初学者,求指点。。

    直接给个代码下载链接.... http://pan.baidu.com/s/1FfVgq 本人刚刚学习angularJs,感觉双向数据绑定蛮爽的... 之前的代码存在点问题,已修复

  7. EF实现增删改查

    从来没想到过能在这个上面翻车,感慨自学没有培训来得系统啊,废话不多说 ORM:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一 ...

  8. 国产化之路-统信UOS + Nginx + Asp.Net MVC + EF Core 3.1 + 达梦DM8实现简单增删改查操作

    专题目录 国产化之路-统信UOS操作系统安装 国产化之路-国产操作系统安装.net core 3.1 sdk 国产化之路-安装WEB服务器 国产化之路-安装达梦DM8数据库 国产化之路-统信UOS + ...

  9. ASP.NET从零开始学习EF的增删改查

           ASP.NET从零开始学习EF的增删改查           最近辞职了,但是离真正的离职还有一段时间,趁着这段空档期,总想着写些东西,想来想去,也不是很明确到底想写个啥,但是闲着也是够 ...

随机推荐

  1. js中哪些语句在if语句中默认为真

    结论:js中有一个函数是:Boolean(value)这个函数把一个value值转换成相应的boolean值. 当value为以下值是为true:1.任意的非空字符串 .2.任意的非0数字 而当val ...

  2. pagination用法

    pagination用法: 1.html  要用两层div <script src="${app }/pc/js/media/pagination.js"></s ...

  3. Bzoj2165 大楼

    Time Limit: 40 Sec  Memory Limit: 259 MBSubmit: 779  Solved: 285[Submit][Status][Discuss] Descriptio ...

  4. ios手机弹出层上表单的操作,收起键盘焦点错乱的问题

    今天遇到了ios手机下 弹出层上form表单 当收起键盘后,焦点错乱,无法再操作的问题 解决办法 function device() { const u = navigator.userAgent; ...

  5. MySQL 5.7主从复制与主主复制实现细节分析

    0.简介: MySQL作为世界上使用最为广泛的数据库之一,免费是其原因之一.但不可忽略的是它本身的功能的确很强大.随着技术的发展,在实际的生产环境中,由单台MySQL数据库服务器不能满足实际的需求.此 ...

  6. Secret Cow code(USACO)

    题目描述:zxyer为了防止他的标程被别人抄走,他在计算机中的rar文件上设置了一个密码,其中每一个密码都有一个初始字符串,字符串由大写字母组成,且长度不超过30位,每一个密码还有一个询问,询问为一个 ...

  7. 合唱队形(DP)

    原题传送门 这道题目就是裸的DP题, 我们所需要得到的是一个倒V形的数列 即一个上升子序列与下降子序列的合体.. 所以我们只需要做一遍从1到n的最长上升子序列和从n到1的最长上升子序列即可 时间复杂度 ...

  8. FileReader&FileWriter

    FileReader public static void main(String[] args) { //创建文件对象指定要读取的文件路径 File file=new File("d:\\ ...

  9. 多线程之:ThreadLocal

    Java中ThreadLocal类可以使创建的变量只被同一个线程进行读和写操作,即使有多个线程同时执行同一段代码,并且这段代码中又有一个指向同一个ThreadLocal变量的引用,这些线程依然不能看到 ...

  10. ZOJ2112 Dynamic Rankings(整体二分)

    今天学习了一个奇技淫巧--整体二分.关于整体二分的一些理论性的东西,可以参见XRH的<浅谈数据结构题的几个非经典解法>.然后下面是一些个人的心得体会吧,写下来希望加深一下自己的理解,或者如 ...