一,什么是Identity map模式

Identity map是EF获取和缓存数据的模式。
Identity map模式指的是任何数据都只会被加载一次,以map的形式缓存,以唯一的identity来再次获取这些数据。
在EF中,就是在一个Context的生命周期中,所有查询过的数据都会缓存到Context的local中缓存。当再次访问这些数据的时候,就会以主键(identity)从缓存中获取这些数据。

二,关于Identity map模式的验证示例

看看下面这段代码运行的结果:

using (var context = new SchoolContext())
{
result1 = context.Students.ToList();
result1[0].Age = -1;
result2 = context.Students.ToList(); var s1 = context.Students.First(s => s.Id == 1);
var s2 = context.Students.First(s => s.Id == 1);
var s3 = context.Students.First(s => s.Id == 3);
var s4 = context.Students.First(s => s.Id == 3); Debug.Assert(ReferenceEquals(s1, s2));
Debug.Assert(ReferenceEquals(s3, s4));
}

运行之后,会发现s1和s2是同一个引用,s3和s4也是同一个引用。
原因就是在Identity map模式来说,对于唯一的主键,返回的必然是同一个对象。

再来看一个更加有趣的例子

public IEnumerable<Student> GetStudents()
{
List<Student> result1;
List<Student> result2;
using (var context = new SchoolContext())
{
result1 = context.Students.ToList();
result1[0].Age = -1;
result2 = context.Students.ToList();
}
return result2;
}

实际的数据库中的result1[0].Age是18,如果修改Age是-1, 再次执行context.Students.ToList(), 返回数据的Age并不是数据库中的18,而是-1.

但是根据MiniProfiler的监控结果,EF的确访问了2次数据库

从这里,得出的结论是:

Context在一次查询结束后,得到的数据会保存到本地缓存,在提交之前对数据的修改都是在本地进行。
当再次Qeury的时候,Context中不存在的数据会放到Context中,Context已经存在的数据(即使被修改了),也不会被数据库的数据覆盖。

三. Unit of Work 模式

Unit of Work模式指的是:

所有对于context中查询得到的实体对象的数据修改,都只会在调用SaveChanges方法后,才会真正的保存到数据库中。你可以在一个Context的生命周期中,修改多个实体对象的值,然后一次提交保存。
在EF中,由于Unit of Work模式,没有办法做选择性的保存数据,只要是数据发生了改动,都会在SaveChnage方法中一并提交到数据库中保存。

四,总结和注意问题

结合这两种模式,可以看出
在一个Context的生命周期中,一个Entity只会有一个实例,任何对该实例的修改,即使这些改动没有保存到数据库中,修改都会影响到整个Context的生命周期。

注意问题:

1. 在使用EF的时候,理想的方式应该是 获取数据-> 修改数据,保存数据->获取数据……的过程。
不要在修改数据的过程中,再次请求数据,因为这些数据很可能和数据库中的数据不一致。

2. 在显示层,最好使用ViewModel, 而不要直接使用EF中Model.
比如一篇博客文章中,我只想显示前500个字给非注册用户看,如果使用Model, 不小心直接将文章内容的字段修改了,只保留了500个字,然后最后调用了SaveChange,用来保存文章的阅读次数。
这样就会导致文章内容被我不小心给丢失了。

最新文章

  1. Kotlin与Android SDK 集成(KAD 05)
  2. ajax实现下拉菜单无刷新加载更多
  3. Java 集合系列08之 List总结(LinkedList, ArrayList等使用场景和性能分析)
  4. POJ 1195 二维树状数组
  5. NetworkComms V3 之支持TCP连接和UDP连接
  6. ELK日志管理
  7. DSP连接不上CCS3.3的问题讨论
  8. uboot之位置无关代码解析
  9. PM过程能力成熟度3级
  10. 处女座与复读机 DP
  11. 在码云(gitee)上展开程序类课程教学
  12. 个人爱好:idea 项目结构呈现风格
  13. vue的全局方法和局部方法
  14. Codeforces Round #435 (Div. 2)
  15. postman创建mocker Server
  16. 在vscode中使用webpack中安装的echarts文件失败,dom获取class名,图表不显示
  17. C#图片增加水印
  18. ASP.NET-自定义HttpModule与HttpHandler介绍
  19. iOS:详解MJRefresh刷新加载更多数据的第三方库
  20. Excel拼接字符串

热门文章

  1. Newtonsoft.Json之JArray, JObject, JProperty,JValue
  2. laravel模型建立和数据迁移和数据填充(数据填充没有成功)未完
  3. SpringCloud系列一:微服务理解
  4. junit测试时报No runnable methods错误的解决方法
  5. cocos2dx游戏 地图
  6. Parencodings - poj 1068
  7. Android Studio SDK Manager 解决无法更新问题
  8. 【Mac系统】之fiddler下载和安装
  9. Android异步处理四:AsyncTask的实现原理
  10. C语言基础知识【循环】