NewLife/FeiXian

批量获取sql后再执行写入操作
大石头 编写于 2020-11-08 19:09:05
共计: 修改1个文件,增加69行、删除35行。
修改 +69 -35
修改 +69 -35
diff --git a/FeiXian.Client/DataSimulation.cs b/FeiXian.Client/DataSimulation.cs
index af01c7d..56e943f 100644
--- a/FeiXian.Client/DataSimulation.cs
+++ b/FeiXian.Client/DataSimulation.cs
@@ -2,16 +2,22 @@
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
+using NewLife.Data;
 using NewLife.Log;
 using NewLife.Model;
+using NewLife.Reflection;
 using NewLife.Security;
 using XCode;
 using XCode.DataAccessLayer;
 
 namespace FeiXian.Client
 {
+    delegate String GetBatchSqlDelegate(IDataTable table, IDataColumn[] columns, ICollection<String> updateColumns, ICollection<String> addColumns, IEnumerable<IExtend> list);
+
     /// <summary>数据模拟</summary>
     public class DataSimulate
     {
@@ -48,7 +54,7 @@ namespace FeiXian.Client
 
             var fact = Factory;
             var session = fact.Session;
-            var pst = fact.Persistence;
+            //var pst = fact.Persistence;
             var conn = fact.Table.ConnName;
 
             // 禁用自动关闭连接,避免频繁开关连接影响性能
@@ -58,6 +64,16 @@ namespace FeiXian.Client
             // 不必获取自增返回值
             fact.AutoIdentity = false;
 
+            // 使用Sql
+            GetBatchSqlDelegate pst = null;
+            if (UseSql)
+            {
+                var method = session.Dal.Session.GetType().GetMethod("GetBatchSql", BindingFlags.Instance | BindingFlags.NonPublic);
+                if (method == null) throw new InvalidOperationException($"数据库[{session.Dal.DbType}]不支持获取批量Sql");
+
+                pst = method.As<GetBatchSqlDelegate>(session.Dal.Session);
+            }
+
             Console.WriteLine();
             WriteLog("数据模拟 Count={0:n0} Threads={1} BatchSize={2} UseSql={3} BatchInsert={4}", count, Threads, BatchSize, UseSql, BatchInsert);
 
@@ -76,9 +92,9 @@ namespace FeiXian.Client
             var sw = Stopwatch.StartNew();
             Parallel.For(0, cpu, n =>
             {
-                //WriteLog("正在准备数据[CPU={0}]:", n);
                 try
                 {
+                    var es = new List<IEntity>();
                     var k = 0;
                     for (var i = n; i < count; i += cpu, k++)
                     {
@@ -96,13 +112,11 @@ namespace FeiXian.Client
                             else if (item.Type == typeof(DateTime))
                                 e[item.Name] = DateTime.Now.AddSeconds(Rand.Next(-10000, 10000));
                         }
-                        var sql = "";
-                        if (UseSql) sql = pst.GetSql(session, e, DataObjectMethodType.Insert);
-                        lock (list)
-                        {
-                            list.Add(e);
-                            if (UseSql) qs.Add(sql);
-                        }
+                        es.Add(e);
+                    }
+                    lock (list)
+                    {
+                        list.AddRange(es);
                     }
                 }
                 catch (Exception ex)
@@ -110,6 +124,18 @@ namespace FeiXian.Client
                     XTrace.WriteException(ex);
                 }
             });
+            if (UseSql)
+            {
+                var columns = fact.Fields.Select(e => e.Field).Where(e => !e.Identity).ToArray();
+                for (int i = 0; i < list.Count;)
+                {
+                    var es = list.Skip(i).Take(BatchSize).ToList();
+                    var sql = pst(session.Table, columns, null, null, es);
+                    qs.Add(sql);
+
+                    i += es.Count;
+                }
+            }
             sw.Stop();
             Console.WriteLine();
             var ms = sw.Elapsed.TotalMilliseconds;
@@ -121,7 +147,6 @@ namespace FeiXian.Client
                 try
                 {
                     //fact.ConnName = conn + n;
-                    session.Dal.Db.ShowSQL = false;
                     fact.FindCount();
                 }
                 catch (Exception ex)
@@ -145,39 +170,48 @@ namespace FeiXian.Client
                 var k = 0;
                 try
                 {
-                    EntityTransaction tr = null;
                     var dal = session.Dal;
-                    var es = new List<IEntity>();
-
-                    for (var i = n; i < list.Count; i += ths, k++)
+                    if (UseSql)
                     {
-                        if (k % BatchSize == 0)
+                        for (var i = n; i < qs.Count; i += ths)
                         {
-                            Console.Write(".");
-
-                            if (UseSql || !BatchInsert)
+                            dal.Session.Execute(qs[i]);
+                            k += BatchSize;
+                        }
+                    }
+                    else
+                    {
+                        EntityTransaction tr = null;
+                        var es = new List<IEntity>();
+                        for (var i = n; i < list.Count; i += ths, k++)
+                        {
+                            if (k % BatchSize == 0)
                             {
-                                tr?.Commit();
-                                if (useTrans) tr = session.CreateTrans();
+                                Console.Write(".");
+
+                                if (!BatchInsert)
+                                {
+                                    tr?.Commit();
+                                    if (useTrans) tr = session.CreateTrans();
+                                }
+                                else
+                                {
+                                    // 批量插入
+                                    //es.Insert(true);
+                                    es.BatchInsert(null, null);
+                                    es.Clear();
+                                }
                             }
+
+                            if (BatchInsert)
+                                es.Add(list[i]);
                             else
-                            {
-                                // 批量插入
-                                //es.Insert(true);
-                                es.BatchInsert(null, null);
-                                es.Clear();
-                            }
+                                list[i].Insert();
                         }
-
-                        if (UseSql)
-                            dal.Execute(qs[i]);
-                        else if (BatchInsert)
-                            es.Add(list[i]);
-                        else
-                            list[i].Insert();
+                        tr?.Commit();
+                        //es.Insert(true);
+                        es.BatchInsert(null, null);
                     }
-                    tr?.Commit();
-                    es.Insert(true);
                 }
                 catch (Exception ex)
                 {