EF批量添加数据性能慢的问题的解决方案

 //EF批量添加数据性能慢的问题的解决方案

        public ActionResult BatchAdd()
        {
            using (var db = new ToneRoad.CEA.DbContext.DbContext())
            {
                //**********************第一种解决方案  直接使用sql**********************

                string sqls = "";
                for (int i = 0; i < 100000; i++)
                {
                    sqls += "sql" + i;
                }
                db.Database.ExecuteSqlCommand(sqls);

                //**********************第二种解决方案  异步并行计算**********************

                List<SYS_User> LIST = new List<SYS_User>();
                ParallelOptions _po = new ParallelOptions();
                _po.MaxDegreeOfParallelism = Environment.ProcessorCount;
                Parallel.ForEach<SYS_User>(LIST, c =>
                {
                    db.SYS_User.Add(c);
                    db.SaveChanges();

                });

                //**********************第三种解决方案 关闭EF跟踪验证**********************

                //关闭 自动跟踪对象的属性变化的功能,默认情况下EF会开启对附加到EF上下文中的实体对象进行校验,看已经附加到上下文中的实体对象的属性是否发生变化,这在大量数据添加时会影响性能。
                db.Configuration.AutoDetectChangesEnabled = false;
                //保存前验证对象的属性最大最小长度等,默认为true,关闭会提高性能
                db.Configuration.ValidateOnSaveEnabled = false;

                List<SYS_User> list = new List<SYS_User>();
                for (int i = 0; i < 100000; i++)
                {
                    SYS_User user = new SYS_User() { UserName = "sa", Password = "123" };
                    list.Add(user);
                }
                db.SYS_User.AddRange(list);
                db.SaveChanges();

                //**********************第四种解决方案 使用SQL Server的bcp命令**********************

                //Microsoft SQL Server 提供的一个称为 bcp(批量流处理)) 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表


                List<SYS_User> lists = new List<SYS_User>();
                for (int i = 0; i < 100000; i++)
                {
                    SYS_User user = new SYS_User() { UserName = "sa", Password = "123" };
                    lists.Add(user);
                }
                BulkCopy<SYS_User>(db, lists);


                return View();
            }
        }
        public void BulkCopy<T>(ToneRoad.CEA.DbContext.DbContext db, IList<T> list)
        {
            using (var con = db.Database.Connection as System.Data.SqlClient.SqlConnection)
            {
                con.Open();

                using (var bulkCopy = new SqlBulkCopy(con))
                {
                    bulkCopy.BatchSize = list.Count;
                    bulkCopy.DestinationTableName = typeof(T).Name;

                    var table = new DataTable();
                    var props = TypeDescriptor.GetProperties(typeof(T))
                        .Cast<PropertyDescriptor>()
                        .Where(propertyInfo => propertyInfo.PropertyType.Namespace.Equals("System"))
                        .ToArray();

                    foreach (var propertyInfo in props)
                    {
                        bulkCopy.ColumnMappings.Add(propertyInfo.Name, propertyInfo.Name);
                        table.Columns.Add(propertyInfo.Name,
                            Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType);
                    }

                    var values = new object[props.Length];
                    foreach (var item in list)
                    {
                        for (var i = 0; i < values.Length; i++)
                        {
                            values[i] = props[i].GetValue(item);
                        }

                        table.Rows.Add(values);
                    }

                    bulkCopy.WriteToServer(table);
                }
                con.Close();
            }
        }
原文地址:https://www.cnblogs.com/eggTwo/p/4288234.html