public Instance[] AnalyseInstance(JArray objs, JObject inherited, string path)
        {
            List <Instance> instances = new List <Instance>();

            for (int i = 0; i < objs.Count; i++)
            {
                MaskingInstance    ins   = new MaskingInstance();
                JObject            obj   = objs[i] as JObject;
                JArray             dbs   = obj["dbs"] as JArray;
                List <MaskingTask> tasks = new List <MaskingTask>();

                for (int j = 0; j < dbs.Count; j++)
                {
                    MaskingTask task = new MaskingTask();

                    AnalyseTask(obj, inherited, dbs[j].ToString(), task, path);
                    tasks.Add(task);
                }

                ins.Tasks = tasks.ToArray();

                if (tasks.Count > 0)
                {
                    ins.Name = $"{tasks[0].Dest.Server}:{tasks[0].Dest.Port}";
                    instances.Add(ins);
                }
            }

            return(instances.ToArray());
        }
        private void MaskTable(MaskingTask task, MaskingTable table, out string reason)
        {
            reason = "取消操作";
            if (status.Stopped)
            {
                return;
            }

            if (Connect(task, task.Dest, out IDBMSReader source, task.Dest, out IDBMSWriter dest))
            {
                Dictionary <string, object> parms = new Dictionary <string, object>();

                dest.QueryParam(task.Params, parms);
                dest.BeginTransaction();
                try
                {
                    // 脱敏数据
                    MaskTableWithScript(task, table, parms, source, dest, out reason);
                    if (table.Status != DataStates.Error && !status.Stopped)
                    {
                        dest.CommitTransaction();
                        table.Status = DataStates.Done;
                    }
                    else
                    {
                        dest.RollbackTransaction();
                        table.Status = DataStates.Error;
                    }
                }
                catch (Exception ex)
                {
                    dest.RollbackTransaction();
                    table.Status = DataStates.Error;
                    reason       = ex.Message;
                }

                source.Close();
                dest.Close();
            }
        private void AnalyseTask(JObject obj, JObject inherited, string db, MaskingTask task, string path)
        {
            task.ReadPages = uint.Parse(GetJValue(obj, inherited, "readPages"));
            task.Threads   = uint.Parse(GetJValue(obj, inherited, "threads"));
            task.Progress  = 0;
            task.Total     = 0;
            task.Status    = DataStates.Idle;
            task.StartTick = 0;

            if (!(task.ReadPages > 0))
            {
                throw new Exception("每次读取数据页数必须大于零(readPages)。");
            }
            if (!(task.Threads > 0))
            {
                throw new Exception("并发脱敏表数必须大于零(threads)。");
            }

            AnalyseDatabase(obj["dest"] as JObject, inherited, task.Dest, db, "dest");
            AnalyseTable($"{path}\\{GetJValue(obj, inherited, "tables")}", task);

            task.Name = $"{task.Dest.DB}";
        }
        private void AnalyseTable(string file, MaskingTask task)
        {
            JObject             obj    = LoadAndDeserialize(file);
            JArray              tables = obj["tables"] as JArray;
            List <MaskingTable> buf    = new List <MaskingTable>();

            task.Params = obj["params"].ToString();

            // #1: 获取所有表
            for (int i = 0; i < tables.Count; i++)
            {
                JObject      o     = tables[i] as JObject;
                string       name  = o["name"].ToString();
                MaskingTable table = new MaskingTable()
                {
                    SourceName   = Table.AnalyseName(name),
                    SourceSchema = Table.AnalyseSchema(name),
                    DestName     = Table.AnalyseName(name),
                    DestSchema   = Table.AnalyseSchema(name),
                    Order        = int.Parse(o["order"].ToString()),
                    OrderSQL     = o["orderSQL"].ToString(),
                    WhereSQL     = o["whereSQL"].ToString(),
                    PageSize     = uint.Parse(o["pageSize"].ToString()),
                    WriteMode    = WriteModes.Append,
                    KeyFields    = o["keyFields"].ToString().Split(','),
                    SkipFields   = new string[] { },
                    MaskFields   = o["maskFields"].ToString().Split(','),
                    Filter       = o["filter"].ToString(),
                    KeepIdentity = false,
                    References   = new string[] { },
                    Total        = 0,
                    Progress     = 0,
                    Status       = DataStates.Idle
                };
                List <string> destFields = new List <string>();

                destFields.AddRange(table.KeyFields);
                destFields.AddRange(table.MaskFields);
                table.DestFields = destFields.ToArray();

                buf.Add(table);

                if (table.WriteMode == WriteModes.Update && "".Equals(table.KeyFields[0]))
                {
                    throw new Exception($"表 {table.SourceName} 配置有误!更新模式必须指定主键字段(keyFields)。");
                }
                if ("".Equals(table.OrderSQL))
                {
                    throw new Exception($"表 {table.SourceName} 配置有误!必须指定稳定的排序规则(orderSQL)。");
                }
                if (table.PageSize <= 0)
                {
                    throw new Exception($"表 {table.SourceName} 配置有误!批量记录数必须大于零(pageSize)。");
                }
                if (string.IsNullOrEmpty(table.Filter))
                {
                    throw new Exception($"表 {table.SourceName} 配置有误!必须指定过滤器(filter)。");
                }
            }

            task.Tables = buf.ToArray();
        }