EntityFramework更新多条数据【8万】
此文主要用做记录用:
原因:数据库迁移,需要转换大量用户资料,两数据某字段加密方式不一致需要批量转换
注:转换程序用了EntityFramework
过程:
1.读取所有需要转换数据至List
2.采用Parallel.ForEach对List进行批次数据转换
3.将转换后的List数据按一定数量进行分割为List<List<T>>
4.建立List<List<T>>相应数量Task数组
5.采用Task.Run建立写入数据库Action
5.运行所有Task[],指令为Task.WaitAll(tasks);
总结:主要是针对写入数据库进行多线程方式处理,读取目前还能忍受,当时用foreach一笔笔写入程序直接假死,半天没反应,后采用多线程写入,效果非常明显
附代码如下:
List<TableName> query; Stopwatch watch = new Stopwatch(); watch.Start(); using (DataBaseConext db = new DataBaseConext()) { db.Configuration.ValidateOnSaveEnabled = false; query = db.apuser.Where(p => p.unpwd != "").ToList(); } watch.Stop(); MessageBox.Show(String.Format("读取使用秒数:{0}", watch.Elapsed.TotalSeconds)); watch.Restart(); Parallel.ForEach<TableName>(query, p => { //SomethingCode }); watch.Stop(); MessageBox.Show(String.Format("轉換使用秒數:{0}", watch.Elapsed.TotalSeconds)); watch.Restart(); List<List<TableName>> users = new List<List<TableName>>(); int splitCount = 1000; while (query.Any()) { users.Add(query.Take(splitCount).ToList()); query = query.Skip(splitCount).ToList(); } Task[] tasks = new Task[users.Count()]; for (int ctr = 0; ctr < users.Count(); ctr++) { var s = users[ctr]; tasks[ctr] = Task.Run(() => { using (DataBaseConext db = new DataBaseConext()) { db.Configuration.ValidateOnSaveEnabled = false; db.Configuration.AutoDetectChangesEnabled = false; s.ForEach(p => { db.Entry<TableName>(p).State = System.Data.Entity.EntityState.Modified; db.SaveChanges(); Debug.WriteLine(String.Format("當前線程編號:{0}", Thread.CurrentThread.ManagedThreadId)); }); } }); } Task.WaitAll(tasks); watch.Stop(); MessageBox.Show(String.Format("分割及保存使用秒數:{0}", watch.Elapsed.TotalSeconds)); MessageBox.Show("完成");