SQLite批量操作优化方案

复制代码
using SQLiteBatch.Util;
using System.Collections.Concurrent;

namespace SQLiteBatch
{
    internal class Program
    {
        static ConcurrentQueue<string> SqlQueue = new ConcurrentQueue<string>();
        static int ExecuteCount = 10000;

        static void Main(string[] args)
        {
            // 初始化
            FreeSqlUtil.InitDB();

            // 单条执行
            Task.Run(() => TaskOne());

            // 批量添加执行
            Task.Run(() => TaskAdd());
            Task.Run(() => TaskUpdate());

            Console.ReadLine();
        }

        static async Task TaskOne()
        {
            var executeStopwatch = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < ExecuteCount; i++)
            {
                await FreeSqlUtil.UpdateChannel_One("Channel1.Device1.400101", i.ToString(), "Good", DateTime.Now.ToString()); 
            }
            executeStopwatch.Stop(); 
            Console.WriteLine($"单条执行, {ExecuteCount} 条 SQL, 总耗时: {executeStopwatch.ElapsedMilliseconds} ms");
        }

        static async Task TaskAdd()
        {
            for (int i = 0; i < ExecuteCount; i++)
            { 
                var sql = FreeSqlUtil.UpdateChannel_Much("Channel1.Device1.400101", i.ToString(), "Good", DateTime.Now.ToString());
                SqlQueue.Enqueue(sql);
            }
        }

        static async Task TaskUpdate()
        { 
            while (true)
            {
                await Task.Delay(10000);

                // 批量取出并执行SQL
                var batchSqls = new List<string>();
                while (SqlQueue.TryDequeue(out string? sql)) batchSqls.Add(sql);

                if (batchSqls.Count > 0)
                {
                    var executeStopwatch = System.Diagnostics.Stopwatch.StartNew();
                    await FreeSqlUtil.ExecuteBatchAsync(batchSqls);
                    executeStopwatch.Stop(); 
                    Console.WriteLine($"批量执行, {batchSqls.Count} 条 SQL, 总耗时: {executeStopwatch.ElapsedMilliseconds} ms");
                } 
            }
        }
    }
}
复制代码
using System.Data.Common;

namespace SQLiteBatch.Util
{
    public class FreeSqlUtil
    {
        static IFreeSql freeSql;

        public static void InitDB()
        {
            var ConnectionString = $"Data source={AppDomain.CurrentDomain.SetupInformation.ApplicationBase}{Path.DirectorySeparatorChar}Data.db";
            freeSql = new FreeSql.FreeSqlBuilder()
                        .UseConnectionString(FreeSql.DataType.Sqlite, ConnectionString)
                        .UseNoneCommandParameter(true)// 不使用参数化
                        .Build();
        }

        public static async Task<bool> UpdateChannel_One(string tag, string value, string quality, string timestamp)
        {
            bool ret = false;
            try
            {
                ret = await freeSql.Update<Channel>()
                    .Set(it => it.OPCValue == value)
                    .Set(it => it.OPCQuality == quality)
                    .Set(it => it.OPCTime == timestamp)
                    .Where(it => it.OPCTag == tag).ExecuteAffrowsAsync() > 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"FreeSqlHelper,UpdateChannel,errmsg:{ex.Message}\r\nstacktrace:{ex.StackTrace}");
            }
            return ret;
        }

        public static string UpdateChannel_Much(string tag, string value, string quality, string timestamp)
        {
            return freeSql.Update<Channel>()
                  .Set(it => it.OPCValue == value)
                  .Set(it => it.OPCQuality == quality)
                  .Set(it => it.OPCTime == timestamp)
                  .Where(it => it.OPCTag == tag).ToSql();
        }

        // 批量执行方法
        public static async Task ExecuteBatchAsync(List<string> lstBathSql)
        { 
            using (FreeSql.Internal.ObjectPool.Object<DbConnection> conn = freeSql.Ado.MasterPool.Get())
            {
                try
                {
                    using (DbTransaction transaction = conn.Value.BeginTransaction())
                    {
                        try
                        {
                            for (int i = 0; i< lstBathSql.Count; i++)
                            { 
                                try
                                { 
                                    await freeSql.Ado.ExecuteNonQueryAsync(transaction, lstBathSql[i]); 
                                }
                                catch (Exception ex)
                                { 
                                    Console.WriteLine($"ExecuteBatchAsync Error(1),ex:{ex.Message},sql:{lstBathSql[i]}");
                                }
                            }
                            transaction.Commit();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            Console.WriteLine($"ExecuteBatchAsync Error(2),ex:{ex.Message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"ExecuteBatchAsync Error(3),ex:{ex.Message}");
                }
            }
        }
    }
}
相关推荐
FirstFrost --sy1 小时前
MySQL内置函数
数据库·mysql
2401_879693871 小时前
将Python Web应用部署到服务器(Docker + Nginx)
jvm·数据库·python
reembarkation1 小时前
光标在a-select,鼠标已经移出,下拉框跟随页面滚动
java·数据库·sql
eggwyw1 小时前
MySQL-练习-数据汇总-CASE WHEN
数据库·mysql
星轨zb2 小时前
通过实际demo掌握SpringSecurity+MP中的基本框架搭建
数据库·spring boot·spring security·mp
treacle田2 小时前
达梦数据库-配置本地守护进程dmwatcher服务-记录总结
数据库·达梦数据库·达梦数据库local数据守护
wyt5314292 小时前
Redis的安装教程(Windows+Linux)【超详细】
linux·数据库·redis
CeshirenTester2 小时前
从数据库到结构化用例:一套可落地的测试智能体架构
数据库·架构
2301_793804693 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python
不想看见4044 小时前
Qt 项目中实现良好封装(模块化设计)的详细流程指南
数据库·系统架构