首先上个错误的版本。
1 public int SaveMany(List<Lotterys> dataList) 2 { 3 using (var db = base.NewDB()) 4 { 5 if (dataList.Count == 0) 6 return 0; 7 8 int count = 0; 9 foreach (var item in dataList) 10 { 11 db.Entry(item).State = System.Data.Entity.EntityState.Added; 12 count += db.SaveChanges(); 13 } 14 return count; 15 } 16 }
为什么错误?
许多人应该看出来了。最大的错误就是每保存一条数据就执行SaveChanges()方法,执行一次SaveChanges()方法要耗费很多时间。并且这个思路也不对。SaveChanges,是事务提交,提交一次会自动释放数据库连接。
我们先试试这种写法1W条数据要多久。估计要炸!(PS:测试环境为wind10,VS2015,EF6.0,MySql,电脑内存8G,Cpu I7-7500U。就一般工作电脑就是了)
终于是出来了...7分钟...
现在进行第二种错误版本。
1 public int SaveMany(List<Lotterys> dataList) 2 { 3 using (var db = base.NewDB()) 4 { 5 if (dataList.Count == 0) 6 return 0; 7 8 foreach (var item in dataList) 9 { 10 db.Entry(item).State = System.Data.Entity.EntityState.Added; 11 } 12 return db.SaveChanges(); 13 } 14 }
这个版本,我自己也踩中了,还是读书少...
优化在将SaveChanges()移出循环,首先将数据插入进EF内存数据中,再执行SaveChanges(),将这些数据提交进数据库,进行持久化。这个坑怎么填稍后说明。
测试下...1分钟15秒...
这个版本的坑在于循环,我们将数据循环插入内存数据中这边浪费了很多时间。看终极版本。
1 public int SaveMany(List<Lotterys> dataList) 2 { 3 using (var db = base.NewDB()) 4 { 5 if (dataList.Count == 0) 6 return 0; 7 8 db.Set<Lotterys>().AddRange(dataList); 9 return db.SaveChanges(); 10 } 11 }
老规矩,测试下...
这次是直接使用EF中内置方法db.Set<T>().AddRange()方法。这个方法说明是将数据放入EF基础数据中,并将其标记为添加状态也就是 db.Entry<T>(entity).State = System.Data.Entity.EntityState.Added;并在执行SaveChange()时将数据提交到数据库。
可以看到在没有循环的时候数据加入极快。保存也非常的迅速。
我这次多截图将程序运行的状态显示出来了,大家可以看到在执行建立数据,和保存数据这边CPU使用率是暴涨的,并且结果也很快8秒,说明程序是充分利用了系统资源的。
再测试个10W条嘿嘿...
10W条数据1分30秒,经多次测量,10W条数据一般在90-120(秒)之间。
好了坑填完了。欢迎讨论。