using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.SQLite;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace SQLite
{
    public class SQLiteHelper
    {
        #region 静态操作
        public class SQLiteFieldTypeInfo
        {
            /// <summary>
            /// sqlite field 类型
            /// </summary>
            public string FieldType { get; set; }
            /// <summary>
            /// C# 类型
            /// </summary>
            public Type PropertyType { get; set; }

            /// <summary>
            /// C# 类型转 sqlite 字符串
            /// </summary>
            public Func<object, string> PtoS { get; set; } = DefaultToS;

            public Func<object, object> StoP { get; set; } = DefaultToP;

            public static string DefaultToS(object obj)
            {
                return obj.ToString();
            }

            public static object DefaultToP(object obj)
            {
                return obj;
            }

            public SQLiteFieldTypeInfo(string fieldtype, Type propertytype)
            {
                FieldType = fieldtype;
                PropertyType = propertytype;
            }
            public SQLiteFieldTypeInfo(string fieldtype, Type propertytype, Func<object, string> ptos, Func<object, object> stop)
            {
                FieldType = fieldtype;
                PropertyType = propertytype;
                PtoS = ptos;
                StoP = stop;

            }


        }
        public static List<SQLiteFieldTypeInfo> FieldTypeInfo { get; set; }


        static SQLiteHelper()
        {

            FieldTypeInfo = new List<SQLiteFieldTypeInfo>
            {
                new SQLiteFieldTypeInfo("INTEGER",typeof(int),
                        SQLiteFieldTypeInfo.DefaultToS,
                        (obj)=>{
                            return Convert.ToInt32(obj);
                        }
                    ),
                new SQLiteFieldTypeInfo("INTEGER",typeof(Int64)),
                new SQLiteFieldTypeInfo("BOOLEAN",typeof(bool)),
                new SQLiteFieldTypeInfo("DOUBLE",typeof(double),
                        (obj)=>((double)obj).ToStringOfSQLiteFieldType(),
                        (obj)=>{
                            if(obj == DBNull.Value)
                                return double.NaN;
                            else
                                return obj;
                        }
                     ),
                new SQLiteFieldTypeInfo("STRING",typeof(string),
                        (obj)=>((string)obj).ToStringOfSQLiteFieldType(),
                        SQLiteFieldTypeInfo.DefaultToP
                     ),
                new SQLiteFieldTypeInfo("DATETIME",typeof(DateTime),
                        (obj)=>((DateTime)obj).ToStringOfSQLiteFieldType(),
                        SQLiteFieldTypeInfo.DefaultToP
                     )
            };
        }

        public static SQLiteFieldTypeInfo GetFieldTypeInfo(string fieldtype)
        {
            var ftis = from fti in FieldTypeInfo where fti.FieldType == fieldtype select fti;
            if (ftis.Count() > 0)
            {
                return ftis.First();
            }
            else
            {
                return null;
            }
        }
        public class ArrayFieldTypeInfo
        {
            /// <summary>
            /// 属性名
            /// </summary>
            public string PropertyName { get; set; }
            /// <summary>
            /// 数组大小
            /// </summary>
            public int Length { get; set; }

            public ArrayFieldTypeInfo(string propertyname, int length)
            {

                PropertyName = propertyname;
                Length = length;
            }
        }


        public static string GetTableName(Type type)
        {
            var attributes = type.GetCustomAttributes(typeof(TableAttribute), false);
            if (attributes.Count() > 0)
            {
                return ((TableAttribute)attributes.First()).Name;
            }
            else
            {
                return type.Name;
            }
        }

        static string GetCreateTableCommandText_fieldText(Type type, IEnumerable<ArrayFieldTypeInfo> arrayFieldTypeInfos)
        {

            string total_fieldtext = "";
            List<FieldTextIndex> fieldTexts = new List<FieldTextIndex>();

            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (var propertyInfo in propertyInfos)
            {
                //忽略
                if (propertyInfo.GetCustomAttributes(typeof(IgnoreAttribute), false).Count() > 0)
                    continue;

                FieldTextIndex fieldText = new FieldTextIndex();
                fieldTexts.Add(fieldText);
                PropertyIndexAttribute propertyIndex = propertyInfo.GetCustomAttribute(typeof(PropertyIndexAttribute)) as PropertyIndexAttribute;
                if (propertyIndex != null)
                    fieldText.index = propertyIndex.Index;//默认index=0


                //这个属性 下面的全部属性,是同一个表
                if (propertyInfo.GetCustomAttributes(typeof(BortherAttribute), false).Count() > 0)
                {
                    //从arrayFieldTypeInfos 提取
                    string startswith = propertyInfo.Name + ".";
                    var aftis = from afti in arrayFieldTypeInfos
                                where afti.PropertyName.StartsWith(startswith)
                                select new ArrayFieldTypeInfo(afti.PropertyName.Substring(startswith.Length), afti.PropertyName.Length);
                    fieldText.fieldtext = GetCreateTableCommandText_fieldText(propertyInfo.PropertyType, aftis);
                    continue;
                }

                if (propertyInfo.PropertyType.IsArray)//是数组,需要明确大小
                {
                    int length = arrayFieldTypeInfos.First((a) => a.PropertyName == propertyInfo.Name).Length;

                    Type elementType = propertyInfo.PropertyType.GetElementType();

                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == elementType);
                    string text = "";
                    for (int i = 0; i < length; i++)
                    {
                        if (i != 0)
                            text += ",";

                        text += string.Format("{0}{1} {2}",
                            propertyInfo.Name,
                            i,
                            fieldTypeInfo.FieldType);
                    }
                    fieldText.fieldtext = text;

                }
                else
                {
                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == propertyInfo.PropertyType);
                    string text = "";
                    text += string.Format("{0} {1}", propertyInfo.Name, fieldTypeInfo.FieldType);

                    //主键
                    if (propertyInfo.GetCustomAttributes(typeof(KeyAttribute), false).Count() > 0)
                        text += " PRIMARY KEY";
                    fieldText.fieldtext = text;
                }
            }
            //从小到大排序
            fieldTexts.Sort((fieldTextIndex0, fieldTextIndex1) =>
            {
                if (fieldTextIndex0.index < fieldTextIndex1.index)
                    return -1;
                if (fieldTextIndex0.index > fieldTextIndex1.index)
                    return 1;
                else
                    return 0;
            });

            for (int i = 0; i < fieldTexts.Count(); i++)
            {
                var fieldTextIndex = fieldTexts[i];
                if (i != 0)
                    total_fieldtext += ",";
                total_fieldtext += fieldTextIndex.fieldtext;
            }
            return total_fieldtext;
        }
        public static string GetCreateTableCommandText(Type type, params ArrayFieldTypeInfo[] arrayFieldTypeInfos)
        {
            if (arrayFieldTypeInfos == null)
                arrayFieldTypeInfos = new ArrayFieldTypeInfo[0];

            //CREATE TABLE table_name(
            //column1 datatype  PRIMARY KEY,
            //column2 datatype,
            //   column3 datatype,
            //   .....
            //   columnN datatype,
            //)
            string tablename = GetTableName(type);
            string fieldtext = GetCreateTableCommandText_fieldText(type, arrayFieldTypeInfos);
            string commandText = string.Format("CREATE TABLE {0} ({1})", tablename, fieldtext);
            return commandText;
        }

        class FieldTextIndex
        {
            public int index = 0;
            public string fieldtext = "";
        }
        static string GetInsertCommandText_fieldText(object cell)
        {
            Type type = cell.GetType();
            string total_fieldtext = "";
            List<FieldTextIndex> fieldTexts = new List<FieldTextIndex>();

            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (var propertyInfo in propertyInfos)
            {
                //忽略
                if (propertyInfo.GetCustomAttributes(typeof(IgnoreAttribute), false).Count() > 0)
                    continue;
                FieldTextIndex fieldText = new FieldTextIndex();
                fieldTexts.Add(fieldText);
                PropertyIndexAttribute propertyIndex = propertyInfo.GetCustomAttribute(typeof(PropertyIndexAttribute)) as PropertyIndexAttribute;
                if (propertyIndex != null)
                    fieldText.index = propertyIndex.Index;//默认index=0

                object o = propertyInfo.GetValue(cell, null);


                //这个属性 下面的全部属性,是同一个表
                if (propertyInfo.GetCustomAttributes(typeof(BortherAttribute), false).Count() > 0)
                {
                    fieldText.fieldtext = GetInsertCommandText_fieldText(o);
                    continue;
                }

                if (propertyInfo.PropertyType.IsArray)//是数组,需要明确大小
                {
                    Type elementType = propertyInfo.PropertyType.GetElementType();

                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == elementType);

                    Array a = o as Array;
                    string text = "";
                    for (int i = 0; i < a.Length; i++)
                    {
                        if (i != 0)
                            text += ",";

                        text += fieldTypeInfo.PtoS(a.GetValue(i));
                    }
                    fieldText.fieldtext = text;
                }
                else
                {
                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == propertyInfo.PropertyType);

                    fieldText.fieldtext = fieldTypeInfo.PtoS(o);
                }
            }

            //从小到大排序
            fieldTexts.Sort((fieldTextIndex0, fieldTextIndex1) =>
            {
                if (fieldTextIndex0.index < fieldTextIndex1.index)
                    return -1;
                if (fieldTextIndex0.index > fieldTextIndex1.index)
                    return 1;
                else
                    return 0;
            });

            for (int i = 0; i < fieldTexts.Count(); i++)
            {
                var fieldTextIndex = fieldTexts[i];
                if (i != 0)
                    total_fieldtext += ",";
                total_fieldtext += fieldTextIndex.fieldtext;
            }
            return total_fieldtext;
        }
        public static string GetInsertCommandText(object cell)
        {
            //不用
            //INSERT INTO TABLE_NAME[(column1, column2, column3,...columnN)]
            //VALUES(value1, value2, value3,...valueN);

            //使用
            //INSERT INTO TABLE_NAME VALUES(value1, value2, value3,...valueN);

            Type type = cell.GetType();
            string tablename = GetTableName(type);
            string fieldtext = GetInsertCommandText_fieldText(cell);
            string commandText = string.Format("INSERT INTO {0} VALUES({1})", tablename, fieldtext);
            return commandText;
        }


        static string GetUpdateCommandText_fieldText(object cell)
        {
            //UPDATE table_name
            //SET column1 = value1, column2 = value2...., columnN = valueN
            //WHERE[condition];

            Type type = cell.GetType();
            string tablename = GetTableName(type);

            string fieldtext = "";
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (var propertyInfo in propertyInfos)
            {
                //忽略
                if (propertyInfo.GetCustomAttributes(typeof(IgnoreAttribute), false).Count() > 0)
                    continue;

                if (fieldtext != "")
                {
                    fieldtext += ",";
                }

                object o = propertyInfo.GetValue(cell, null);

                //这个属性 下面的全部属性,是同一个表
                if (propertyInfo.GetCustomAttributes(typeof(BortherAttribute), false).Count() > 0)
                {
                    fieldtext += GetUpdateCommandText_fieldText(o);
                    continue;
                }

                if (propertyInfo.PropertyType.IsArray)//是数组,需要明确大小
                {
                    Type elementType = propertyInfo.PropertyType.GetElementType();

                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == elementType);

                    Array a = o as Array;

                    for (int i = 0; i < a.Length; i++)
                    {
                        if (i != 0)
                            fieldtext += ",";

                        fieldtext += string.Format("{0}{1} = {2}", propertyInfo.Name, i, fieldTypeInfo.PtoS(a.GetValue(i)));
                    }
                }
                else
                {
                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == propertyInfo.PropertyType);


                    fieldtext += string.Format("{0} = {1}", propertyInfo.Name, fieldTypeInfo.PtoS(o));
                }
            }

            return fieldtext;
        }
        /// <summary>
        /// condition 为 "WHERE ......"
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="condition"></param>
        /// <returns></returns>
        public static string GetUpdateCommandText(object cell, string condition)
        {
            //UPDATE table_name
            //SET column1 = value1, column2 = value2...., columnN = valueN
            //WHERE[condition];

            Type type = cell.GetType();
            string tablename = GetTableName(type);
            string fieldtext = GetUpdateCommandText_fieldText(cell);
            string commandText = $"UPDATE {tablename} SET {fieldtext}";

            if (!string.IsNullOrEmpty(condition))
                commandText += $" {condition}";

            return commandText;
        }

        public static List<T> ToObjs<T>(DataTable dataTable, params ArrayFieldTypeInfo[] arrayFieldTypeInfos)
            where T : new()
        {
            Type type = typeof(T);
            List<T> list = new List<T>();
            foreach (DataRow dataRow in dataTable.Rows)
            {
                list.Add(ToObj<T>(dataRow, arrayFieldTypeInfos));
            }
            return list;
        }

        static void SetObj(object t, DataRow dataRow, IEnumerable<ArrayFieldTypeInfo> arrayFieldTypeInfos)
        {
            Type type = t.GetType();

            PropertyInfo[] propertyInfos = type.GetProperties();

            foreach (var propertyInfo in propertyInfos)
            {
                //忽略
                if (propertyInfo.GetCustomAttributes(typeof(IgnoreAttribute), false).Count() > 0)
                    continue;

                Type ptype = propertyInfo.PropertyType;

                //这个属性 下面的全部属性,是同一个表
                if (propertyInfo.GetCustomAttributes(typeof(BortherAttribute), false).Count() > 0)
                {
                    //从arrayFieldTypeInfos 提取
                    string startswith = propertyInfo.Name + ".";
                    var aftis = from afti in arrayFieldTypeInfos
                                where afti.PropertyName.StartsWith(startswith)
                                select new ArrayFieldTypeInfo(afti.PropertyName.Substring(startswith.Length), afti.PropertyName.Length);

                    object obj = propertyInfo.GetValue(t, null);
                    SetObj(obj, dataRow, aftis);
                    continue;
                }


                if (ptype.IsArray)//是数组,需要明确大小
                {
                    Type elementType = propertyInfo.PropertyType.GetElementType();
                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == elementType);
                    int length = arrayFieldTypeInfos.First((a) => a.PropertyName == propertyInfo.Name).Length;

                    Array array = (Array)ptype.Assembly.CreateInstance(ptype.FullName, false, BindingFlags.CreateInstance, null, new object[] { length }, null, null);
                    for (int i = 0; i < length; i++)
                    {
                        object o = fieldTypeInfo.StoP(dataRow[propertyInfo.Name + i]);
                        array.SetValue(o, i);
                    }
                    propertyInfo.SetValue(t, array, null);
                }
                else
                {
                    SQLiteFieldTypeInfo fieldTypeInfo = FieldTypeInfo.Find((fti) => fti.PropertyType == ptype);
                    object o = fieldTypeInfo.StoP(dataRow[propertyInfo.Name]);
                    propertyInfo.SetValue(t, o, null);
                }
            }
        }
        public static T ToObj<T>(DataRow dataRow, params ArrayFieldTypeInfo[] arrayFieldTypeInfos)
            where T : new()
        {
            Type type = typeof(T);
            T t = new T();
            SetObj(t, dataRow, arrayFieldTypeInfos);
            return t;
        }

        #endregion


        public string ConnectionString;
        /// <summary> 
        /// 查询数据库中的所有数据类型信息。
        /// </summary> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public DataTable ExecuteReader(string sql)
        {
            DataTable data;
            using (SQLiteConnection connection = new SQLiteConnection(ConnectionString))
            {
                using (SQLiteCommand command = new SQLiteCommand(connection))
                {
                    connection.Open();
                    command.CommandText = sql;
                    // 开始读取
                    SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
                    data = new DataTable();
                    adapter.Fill(data);
                    connection.Close();
                }

            }
            return data;
        }
        /// <summary> 
        /// 对SQLite数据库执行增删改操作,返回受影响的行数。 
        /// </summary> 
        /// <param name="sql">要执行的增删改的SQL语句。</param> 
        /// <param name="parameters">执行增删改语句所需要的参数,参数必须以它们在SQL语句中的顺序为准。</param> 
        /// <returns></returns> 
        /// <exception cref="Exception"></exception>
        public void ExecuteNonQuery(string sql)
        {
            using (SQLiteConnection connection = new SQLiteConnection(ConnectionString))
            {
                using (SQLiteCommand command = new SQLiteCommand(connection))
                {
                    connection.Open();
                    command.CommandText = sql;
                    command.ExecuteNonQuery();
                    connection.Close();
                }
            }
        }


        /// <summary>
        ///     
        /// </summary>
        /// <param name="sql"></param>
        /// <returns>The first column of the first row of the first resultset from the query.</returns>
        public object ExecuteScalar(string sql)
        {
            object obj = null;
            using (SQLiteConnection connection = new SQLiteConnection(ConnectionString))
            {
                using (SQLiteCommand command = new SQLiteCommand(connection))
                {
                    connection.Open();
                    command.CommandText = sql;
                    obj = command.ExecuteScalar();
                    connection.Close();
                }
            }
            return obj;
        }
        /// <summary>
        /// 多行执行
        /// </summary>
        /// <param name="queryList"></param>
        /// <returns></returns>
        public bool QueryTran(IEnumerable<string> queryList)
        {
            if (isHoldQueryTran)
            {
                holdQueryList.AddRange(queryList);
                return true;
            }
            else
            {
                using (SQLiteConnection connection = new SQLiteConnection(ConnectionString))
                {
                    using (SQLiteCommand command = new SQLiteCommand(connection))
                    {
                        connection.Open();

                        SQLiteTransaction tran = connection.BeginTransaction();
                        bool check = false;
                        try
                        {
                            foreach (string item in queryList)
                            {
                                command.CommandText = item;
                                command.ExecuteNonQuery();
                            }
                            tran.Commit();
                            check = true;
                        }
                        catch (Exception ex)
                        {
                            tran.Rollback();
                            check = false;
                            throw ex;
                        }
                        finally
                        {
                            connection.Close();
                        }
                        return check;
                    }
                }
            }

        }

        /// <summary>
        /// 异步
        /// </summary>
        /// <param name="queryList"></param>
        /// <returns></returns>
        public void QueryTranAsync(IEnumerable<string> queryList)
        {
            new Task((obj) => {
                var _sqls = obj as IEnumerable<string>;
                QueryTran(_sqls);
            }, queryList).Start(StepByStepTaskScheduler.Current);
        }

        List<string> holdQueryList = new List<string>();
        bool isHoldQueryTran = false;
        public void HoldQueryTran()
        {
            isHoldQueryTran = true;
        }
        public bool ReleaseQueryTran()
        {
            if (holdQueryList.Count() > 0)
            {
                using (SQLiteConnection connection = new SQLiteConnection(ConnectionString))
                {
                    using (SQLiteCommand command = new SQLiteCommand(connection))
                    {
                        connection.Open();

                        SQLiteTransaction tran = connection.BeginTransaction();
                        bool check = false;
                        try
                        {
                            foreach (string item in holdQueryList)
                            {
                                command.CommandText = item;
                                command.ExecuteNonQuery();
                            }
                            tran.Commit();
                            check = true;
                        }
                        catch (Exception ex)
                        {
                            tran.Rollback();
                            check = false;
                            throw ex;
                        }
                        finally
                        {
                            holdQueryList.Clear();
                            connection.Close();
                            isHoldQueryTran = false;
                        }
                        return check;
                    }
                }
            }
            isHoldQueryTran = false;
            return true;
        }
        /// <summary>
        /// 出错代码
        /// </summary>
        public string ErrorMsg { get; set; }
        /// <summary>
        /// 输入DDLs 判断这些table都是否合法
        /// </summary>
        /// <param name="DDLs">key=tablename, value=DDL</param>
        /// <returns></returns>
        public bool IsTableValid(Dictionary<string, string> DDLs)
        {

            //检测 table 是否合法
            DataTable data = ExecuteReader("SELECT name,sql FROM sqlite_master WHERE type = 'table'");

            //任意一个表不对,或者不存在,都必须重建
            bool isVaild = true;
            foreach (var kv in DDLs)
            {
                string tablename = kv.Key;
                string createtable_sql = kv.Value;

                var sqls = from r in data.AsEnumerable() where (string)r["name"] == tablename select r["sql"];
                if (sqls.Count() == 0)
                {
                    //不存在该表,创建
                    isVaild = false;
                    break;
                }
                else
                {
                    string sql = (string)sqls.First();
                    if (sql != createtable_sql)
                    {
                        if (!GetTableInfoFromDDL(sql, out SQLiteTableInfo tableInfo0))
                        {
                            ErrorMsg = $"sqlite_master 找到 name = '{tablename}' 的 sql 不能解析";
                            isVaild = false;
                            break;
                        }
                        if (!GetTableInfoFromDDL(createtable_sql, out SQLiteTableInfo tableInfo1))
                        {
                            ErrorMsg = $"程序中 name = '{tablename}' 的 sql 不能解析";
                            isVaild = false;
                            break;
                        }

                        if (!tableInfo0.Equals(tableInfo1))
                        {
                            ErrorMsg = $"sqlite_master 找到 name = '{tablename}' 的 sql 不符合要求, " + tableInfo0.ErrorMsg;
                            isVaild = false;
                            break;
                        }
                    }
                }
            }
            return isVaild;
        }

        public bool GetTableInfoFromDDL(string DDL, out SQLiteTableInfo tableInfo)
        {
            tableInfo = null;
            Regex regex_key = new Regex(@"PRIMARY KEY");
            //CREATE TABLE boltmap(ID INTEGER PRIMARY KEY, MID INTEGER, RBegin INTEGER, REnd INTEGER)
            Regex regex = new Regex(@"CREATE TABLE\s+(\w+)\s+\((.+)\)");
            Match match = regex.Match(DDL);
            if (!match.Success)
            {
                ErrorMsg = "不能匹配 CREATE TABLE 的格式";
                return false;
            }
            tableInfo = new SQLiteTableInfo();
            tableInfo.Name = match.Groups[1].Value;

            string fields_sql = match.Groups[2].Value;
            string[] fields_str = fields_sql.Split(',');
            foreach (string str in fields_str)
            {
                SQLiteFieldInfo fieldInfo = new SQLiteFieldInfo();
                string str1 = str.Trim();
                string[] ss = str1.Split(' ');
                if (ss.Length < 2)
                {
                    ErrorMsg = $"{str1} 格式出错";
                    return false;
                }
                fieldInfo.Name = ss[0];
                fieldInfo.Type = ss[1];
                if (regex_key.IsMatch(str1))
                    fieldInfo.IsKey = true;
                tableInfo.FieldInfos.Add(fieldInfo);
            }
            return true;
        }
    }

    public class SQLiteTableInfo
    {
        /// <summary>
        /// 名称
        /// </summary>
        public string Name;
        public List<SQLiteFieldInfo> FieldInfos = new List<SQLiteFieldInfo>();
        public override bool Equals(object obj)
        {
            SQLiteTableInfo tableinfo = obj as SQLiteTableInfo;
            if (tableinfo.Name != Name)
            {
                ErrorMsg = $"名称不相等 期待.{tableinfo.Name}!=数据库.{Name}";
                return false;
            }
            if (tableinfo.FieldInfos.Count() != FieldInfos.Count())
            {
                ErrorMsg = $"field 数量不同 期待.{tableinfo.FieldInfos.Count()}!=数据库.{FieldInfos.Count()}";
                return false;
            }
            for (int i = 0; i < FieldInfos.Count(); i++)
            {
                if (!FieldInfos[i].Equals(tableinfo.FieldInfos[i]))
                {
                    ErrorMsg = $"field 不同 期待.({tableinfo.FieldInfos[i]})!=数据库.({FieldInfos[i]})";
                    return false;
                }
            }
            ErrorMsg = "OK";
            return true;
        }
        public string ErrorMsg { get; set; }
    }
    public class SQLiteFieldInfo
    {
        /// <summary>
        /// 类型
        /// </summary>
        public string Type;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name;
        /// <summary>
        /// 是主键?
        /// </summary>
        public bool IsKey;
        public override bool Equals(object obj)
        {
            SQLiteFieldInfo fieldInfo = obj as SQLiteFieldInfo;
            if (Type != fieldInfo.Type)
                return false;
            if (Name != fieldInfo.Name)
                return false;
            if (IsKey != fieldInfo.IsKey)
                return false;
            return true;
        }
        public override string ToString()
        {
            string s = $"{Name} As {Type}";
            if (IsKey)
                s += " IsKey";
            return s;
        }
    }

    public static class SQLiteFieldTypeExtern
    {
        public static string ToStringOfSQLiteFieldType(this DateTime dt)
        {
            return $"'{dt:yyyy-MM-dd HH:mm:ss.fff}'";
        }
        public static string ToStringOfSQLiteFieldType(this string str)
        {
            return $"'{str}'";
        }
        public static string ToStringOfSQLiteFieldType(this double d)
        {
            if (double.IsNaN(d))
                return "NULL";
            else return d.ToString();
        }
    }


    public class StepByStepTaskScheduler : TaskScheduler
    {
        public static new TaskScheduler Current { get; } = new StepByStepTaskScheduler();
        public static new TaskScheduler Default { get; } = Current;

        public static StepByStepTaskScheduler Instance { get; } = (StepByStepTaskScheduler)Current;
        private readonly BlockingCollection<Task> m_queue = new BlockingCollection<Task>();

        StepByStepTaskScheduler()
        {
            //Thread thread = new Thread(Run);
            //thread.IsBackground = true;//设为为后台线程,当主线程结束时线程自动结束
            //thread.Start();
            Task.Factory.StartNew(Run);
        }

        private void Run()
        {
            //Console.WriteLine($"MyTaskScheduler, ThreadID: {Thread.CurrentThread.ManagedThreadId}");
            Task t;
            while (m_queue.TryTake(out t, System.Threading.Timeout.Infinite))
            {
                TryExecuteTask(t);//在当前线程执行Task
            }
        }

        protected override IEnumerable<Task> GetScheduledTasks()
        {
            return m_queue;
        }
        public BlockingCollection<Task> ScheduledTasks
        {
            get { return m_queue; }
        }
        protected override void QueueTask(Task task)
        {
            m_queue.Add(task);//t.Start(MyTaskScheduler.Current)时,将Task加入到队列中
        }

        //当执行该函数时,程序正在尝试以同步的方式执行Task代码
        protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
        {
            return false;
        }
    }
}