要专业系统地学习EF推荐《你必须掌握的Entity Framework 6.x与Core 2.0》。这本书作者(汪鹏,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/
上一篇我们知道了快照和代理怎么回事,所以来测试看看
测试添加操作,插入一千条数据看看
快照五次,时间分别为: 1335ms 635ms 1025ms 1242ms 717ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//快照插入一千条数据 var watch = new Stopwatch(); watch.Start(); List<Book> books = new List<Book>(); for (int i = 0; i < 1000; i++) { books.Add(new Book { Name = $"book{i + 1}", PageSize = 1000 + i, AddTime = DateTime.Now }); } ctx.Books.AddRange(books); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
代理添加,时间分别为: 1287ms 701ms 1460ms 1289ms 968ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 代理插入一千条数据 ctx.Configuration.AutoDetectChangesEnabled = false; var watch = new Stopwatch(); watch.Start(); ctx.Database.Log = Console.WriteLine; List<Book> books = new List<Book>(); for (int i = 0; i < 3000; i++) { books.Add(new Book { Name = $"book{i + 1}", PageSize = 1000 + i, AddTime = DateTime.Now }); } ctx.Books.AddRange(books); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
有一个问题,添加一千条数据,EF是逐条添加的,但是顺序为什么不对呢?
再来看看修改数据,我们对三千条数据进行修改
快照追踪方式,我记录了两组数据
1、1692ms 518ms 474ms 561ms 519ms 为什么这后面的几个同时这么短?那是因为我没有改代码,继续执行修改,那么其实虽然说给属性赋值了,但并没有修改,EF也不会去执行
2、3303ms 2724ms 2250ms 2796ms 现在我就将每一次修改的数据进行改变
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var watch = new Stopwatch(); watch.Start(); var books = ctx.Books.ToList(); books.ForEach(book => { book.Name = "book"; book.PageSize = 999; book.AddTime = new DateTime(1999, 9, 9); }); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
代理方式,现在就有差距了,会比快照耗时一些
1、3010ms 3144ms 1851ms 2989ms
2、1788ms 3006ms 2738ms 1681ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ctx.Configuration.AutoDetectChangesEnabled = false; var watch = new Stopwatch(); watch.Start(); var books = ctx.Books.ToList(); books.ForEach(book => { book.Name = "book2"; book.PageSize = 888; book.AddTime = new DateTime(1999, 9, 9); }); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
如果说我们只是修改三千条数据中的其中三条呢?
快照追踪
643ms 424ms 609ms 575ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var watch = new Stopwatch(); watch.Start(); var books = ctx.Books.ToList(); books.ForEach(book => { if (book.PageSize < 1003) { book.Name = "book2"; book.PageSize = 777; book.AddTime = new DateTime(1999, 9, 9); } }); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
现在我们把三条之外的两千多条实体的属性也赋值,但是还是原来的值
1838ms 1291ms 2992ms 3175ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var watch = new Stopwatch(); watch.Start(); var books = ctx.Books.ToList(); books.ForEach(book => { if (book.PageSize < 1003) { book.Name = "book2"; book.PageSize = 777; book.AddTime = new DateTime(1999, 9, 9); } else { book.Name = book.Name; book.PageSize = book.PageSize; book.AddTime = book.AddTime; } }); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
代理追踪
584ms 513ms 492ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var watch = new Stopwatch(); watch.Start(); ctx.Configuration.AutoDetectChangesEnabled = fal var books = ctx.Books.ToList(); books.ForEach(book => { if (book.PageSize < 1003) { book.Name = "book"; book.PageSize = 888; book.AddTime = new DateTime(1999, 9, 9); } }); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
3247ms 2481ms 3051ms
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var watch = new Stopwatch(); watch.Start(); ctx.Configuration.AutoDetectChangesEnabled = f var books = ctx.Books.ToList(); books.ForEach(book => { if (book.PageSize < 1003) { book.Name = "book"; book.PageSize = 888; book.AddTime = new DateTime(1999, 9, 9); } else { book.Name = book.Name; book.PageSize = book.PageSize; book.AddTime = book.AddTime; } }); ctx.SaveChanges(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds);
感觉没什么变化,可能是我的数据太少了
最后引用作者的一段话:
“对于代理变更追踪,笔者认为似乎没有什么可用之处,几乎没看见过将属性标记为virtual作为代理类来用,再者EF团队在代理式变更追踪方面并没有过多投入,二者的性能比较就当做了解。
virtual只是用于导航属性的延迟加载,如果我们想用代理式变更追踪,除非真正的理解它的问题并有一个合理的理由去使用它,当然这也就意味着,当用快照式变更追踪遇到性能瓶颈时,可以考虑使用代理式变更追踪(大部分情况下还是不会)”