ActionMesSqliteDataClass.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. using CCDCount.MODEL.ShuLiModel; // 确保引用ActiveObjectClass所在命名空间
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.Data.SQLite;
  6. using System.IO;
  7. using System.Text;
  8. using System.Threading;
  9. namespace CCDCount.DLL.SqlDataClass
  10. {
  11. public class ActionMesSqliteDataClass
  12. {
  13. private string DatabaseFile;
  14. private readonly string _connectionString;
  15. private object locker = new object();
  16. private readonly ConcurrentQueue<ActiveObjectClass> _dataQueue = new ConcurrentQueue<ActiveObjectClass>();
  17. private readonly Timer _timer;
  18. private const int MaxBatchSize = 1000; // 单次最大插入条数(受 SQLite 参数上限限制)
  19. private const int FlushIntervalMs = 5000; // 最大等待时间(毫秒)
  20. public ActionMesSqliteDataClass(string dbPath)
  21. {
  22. DatabaseFile = dbPath;
  23. _connectionString = $"Data Source={DatabaseFile};Version=3;"+
  24. "Journal Mode=WAL;" + // 使用WAL模式提高并发性
  25. "Synchronous=Normal;" + // 平衡性能和安全性
  26. "Cache Size=10000;" + // 增加缓存大小
  27. "Pooling=true;" + // 启用连接池
  28. "Max Pool Size=100;"; // 设置最大连接池大小
  29. string directoryPath = Path.GetDirectoryName(DatabaseFile);
  30. if (!Directory.Exists(directoryPath))
  31. {
  32. // 创建文件夹
  33. Directory.CreateDirectory(directoryPath);
  34. }
  35. InitializeDatabase();
  36. _timer = new Timer(FlushData, null, FlushIntervalMs, FlushIntervalMs);
  37. }
  38. private void InitializeDatabase()
  39. {
  40. if (!File.Exists(DatabaseFile))
  41. {
  42. SQLiteConnection.CreateFile(DatabaseFile);
  43. }
  44. using (var conn = new SQLiteConnection(_connectionString))
  45. {
  46. conn.Open();
  47. // 创建主表
  48. const string createActiveObjectTable = @"
  49. CREATE TABLE IF NOT EXISTS ActiveObject (
  50. Id INTEGER PRIMARY KEY AUTOINCREMENT,
  51. Num INTEGER NOT NULL,
  52. MinStartCol INTEGER NOT NULL,
  53. MaxEndCol INTEGER NOT NULL,
  54. LastSeenLineStartCol INTEGER NOT NULL,
  55. LastSeenLineEndCol INTEGER NOT NULL,
  56. StartLine INTEGER NOT NULL,
  57. LastSeenLine INTEGER NOT NULL,
  58. StartCheckTime TEXT NOT NULL,
  59. EndCheckTime TEXT NOT NULL,
  60. Area INTEGER NOT NULL,
  61. MaxLength REAL NOT NULL,
  62. ChannelNO INTEGER NOT NULL,
  63. ImageWidth INTEGER NOT NULL,
  64. StateCode INTEGER NOT NULL DEFAULT -1,
  65. BatchNumber TEXT NOT NULL,
  66. hasSignificantConcavity INTEGER CHECK (hasSignificantConcavity IN (0, 1)),
  67. concavityRatio REAL NOT NULL
  68. )";
  69. // 创建从表
  70. const string createRowDataTable = @"
  71. CREATE TABLE IF NOT EXISTS RowData (
  72. Id INTEGER PRIMARY KEY AUTOINCREMENT,
  73. ActiveObjectId INTEGER NOT NULL,
  74. RowsCol INTEGER NOT NULL,
  75. StartCol INTEGER NOT NULL,
  76. EndCol INTEGER NOT NULL,
  77. FOREIGN KEY (ActiveObjectId)
  78. REFERENCES ActiveObject(Id) ON DELETE CASCADE
  79. )";
  80. using (var cmd = new SQLiteCommand(conn))
  81. {
  82. cmd.CommandText = createActiveObjectTable;
  83. cmd.ExecuteNonQuery();
  84. cmd.CommandText = createRowDataTable;
  85. cmd.ExecuteNonQuery();
  86. }
  87. }
  88. }
  89. // 插入ActiveObjectClass对象及其关联数据
  90. public void AddData(ActiveObjectClass data)
  91. {
  92. _dataQueue.Enqueue(data);
  93. // 如果缓存数量达到上限,则立即触发写入
  94. if (_dataQueue.Count >= MaxBatchSize)
  95. {
  96. FlushData(null);
  97. }
  98. }
  99. // 强制刷新缓存数据到数据库
  100. private void FlushData(object state)
  101. {
  102. lock (locker)
  103. {
  104. if (_dataQueue.IsEmpty) return;
  105. var batch = new List<ActiveObjectClass>();
  106. while (_dataQueue.TryDequeue(out var item))
  107. {
  108. batch.Add(item);
  109. }
  110. WriteBatchToDatabase(batch);
  111. }
  112. }
  113. private void WriteBatchToDatabase(List<ActiveObjectClass> batch)
  114. {
  115. using (var conn = new SQLiteConnection(_connectionString))
  116. {
  117. conn.Open();
  118. using (var transaction = conn.BeginTransaction())
  119. {
  120. try
  121. {
  122. // 获取插入前的最大 ID
  123. var cmdGetMaxId = new SQLiteCommand("SELECT COALESCE(MAX(Id), 0) FROM ActiveObject", conn);
  124. var startId = Convert.ToInt32(cmdGetMaxId.ExecuteScalar()) + 1;
  125. // 构建批量插入语句
  126. var sqlBuilder = new StringBuilder();
  127. sqlBuilder.Append(@"
  128. INSERT INTO ActiveObject (
  129. Num, MinStartCol, MaxEndCol, LastSeenLineStartCol,
  130. LastSeenLineEndCol, StartLine, LastSeenLine,
  131. StartCheckTime, EndCheckTime, Area, MaxLength,
  132. ChannelNO, ImageWidth, StateCode, BatchNumber,
  133. hasSignificantConcavity, concavityRatio
  134. ) VALUES ");
  135. var parameters = new List<object>();
  136. for (int i = 0; i < batch.Count; i++)
  137. {
  138. var obj = batch[i];
  139. sqlBuilder.Append($"(@p{i * 17}, @p{i * 17 + 1}, @p{i * 17 + 2}, @p{i * 17 + 3}, " +
  140. $"@p{i * 17 + 4}, @p{i * 17 + 5}, @p{i * 17 + 6}, " +
  141. $"@p{i * 17 + 7}, @p{i * 17 + 8}, @p{i * 17 + 9}, " +
  142. $"@p{i * 17 + 10}, @p{i * 17 + 11}, @p{i * 17 + 12}, " +
  143. $"@p{i * 17 + 13}, @p{i * 17 + 14}, @p{i * 17 + 15}, @p{i * 17 + 16})");
  144. if (i < batch.Count - 1)
  145. sqlBuilder.Append(", ");
  146. // 绑定参数值
  147. parameters.AddRange(new object[]
  148. {
  149. obj.Num, obj.MinStartCol, obj.MaxEndCol, obj.PreSeenLineStartCol,
  150. obj.PreSeenLineEndCol, obj.StartLine, obj.LastSeenLine,
  151. obj.StartCheckTime.ToString("o"), obj.EndCheckTime.ToString("o"),
  152. obj.Area, obj.MaxLength, obj.ChannelNO, obj.ImageWidth,
  153. obj.StateCode, obj.BatchNumber, obj.hasSignificantConcavity, obj.concavityRatio
  154. });
  155. }
  156. // 执行批量插入
  157. using (var cmd = new SQLiteCommand(sqlBuilder.ToString(), conn))
  158. {
  159. for (int i = 0; i < parameters.Count; i++)
  160. {
  161. cmd.Parameters.AddWithValue($"@p{i}", parameters[i]);
  162. }
  163. cmd.ExecuteNonQuery();
  164. }
  165. // 批量插入 RowData
  166. InsertRowDataBatch(conn, batch, startId);
  167. transaction.Commit();
  168. }
  169. catch
  170. {
  171. transaction.Rollback();
  172. throw;
  173. }
  174. }
  175. }
  176. }
  177. public void InsertActiveObject(ActiveObjectClass activeObject)
  178. {
  179. lock (locker)
  180. {
  181. using (var conn = new SQLiteConnection(_connectionString))
  182. {
  183. conn.Open();
  184. using (var transaction = conn.BeginTransaction())
  185. {
  186. try
  187. {
  188. // 插入主表数据
  189. const string insertActiveObject = @"
  190. INSERT INTO ActiveObject (
  191. Num, MinStartCol, MaxEndCol, LastSeenLineStartCol,
  192. LastSeenLineEndCol, StartLine, LastSeenLine,
  193. StartCheckTime, EndCheckTime, Area, MaxLength,
  194. ChannelNO, ImageWidth, StateCode, BatchNumber,
  195. hasSignificantConcavity,concavityRatio
  196. ) VALUES (
  197. @Num, @MinStartCol, @MaxEndCol, @LastSeenLineStartCol,
  198. @LastSeenLineEndCol, @StartLine, @LastSeenLine,
  199. @StartCheckTime, @EndCheckTime, @Area, @MaxLength,
  200. @ChannelNO, @ImageWidth, @StateCode, @BatchNumber,
  201. @hasSignificantConcavity,@concavityRatio
  202. ); SELECT last_insert_rowid();";
  203. using (var cmd = new SQLiteCommand(insertActiveObject, conn))
  204. {
  205. cmd.Parameters.AddWithValue("@Num", activeObject.Num);
  206. cmd.Parameters.AddWithValue("@MinStartCol", activeObject.MinStartCol);
  207. cmd.Parameters.AddWithValue("@MaxEndCol", activeObject.MaxEndCol);
  208. cmd.Parameters.AddWithValue("@LastSeenLineStartCol", activeObject.PreSeenLineStartCol);
  209. cmd.Parameters.AddWithValue("@LastSeenLineEndCol", activeObject.PreSeenLineEndCol);
  210. cmd.Parameters.AddWithValue("@StartLine", activeObject.StartLine);
  211. cmd.Parameters.AddWithValue("@LastSeenLine", activeObject.LastSeenLine);
  212. cmd.Parameters.AddWithValue("@StartCheckTime", activeObject.StartCheckTime.ToString("o"));
  213. cmd.Parameters.AddWithValue("@EndCheckTime", activeObject.EndCheckTime.ToString("o"));
  214. cmd.Parameters.AddWithValue("@Area", activeObject.Area);
  215. cmd.Parameters.AddWithValue("@MaxLength", activeObject.MaxLength);
  216. cmd.Parameters.AddWithValue("@ChannelNO", activeObject.ChannelNO);
  217. cmd.Parameters.AddWithValue("@ImageWidth", activeObject.ImageWidth);
  218. cmd.Parameters.AddWithValue("@StateCode", activeObject.StateCode);
  219. cmd.Parameters.AddWithValue("@BatchNumber", activeObject.BatchNumber);
  220. cmd.Parameters.AddWithValue("@hasSignificantConcavity", activeObject.hasSignificantConcavity);
  221. cmd.Parameters.AddWithValue("@concavityRatio", activeObject.concavityRatio);
  222. // 获取新插入的主键ID
  223. var activeObjectId = Convert.ToInt32(cmd.ExecuteScalar());
  224. // 插入关联的RowData
  225. InsertRowData(conn, activeObjectId, activeObject.RowsData);
  226. }
  227. transaction.Commit();
  228. }
  229. catch
  230. {
  231. transaction.Rollback();
  232. throw;
  233. }
  234. }
  235. }
  236. }
  237. }
  238. // 批量插入 RowData 数据
  239. private void InsertRowDataBatch(SQLiteConnection conn, List<ActiveObjectClass> batch, int startId)
  240. {
  241. // 先统计总行数,判断是否需要插入
  242. var totalRows = 0;
  243. foreach (var obj in batch)
  244. {
  245. if (obj.RowsData != null && obj.RowsData.Count > 0)
  246. {
  247. totalRows += obj.RowsData.Count;
  248. }
  249. }
  250. if (totalRows == 0)
  251. return;
  252. // 构建批量插入语句
  253. var sqlBuilder = new StringBuilder();
  254. sqlBuilder.Append(@"
  255. INSERT INTO RowData (
  256. ActiveObjectId, RowsCol, StartCol, EndCol
  257. ) VALUES ");
  258. var parameters = new List<object>();
  259. int paramIndex = 0;
  260. int currentId = startId;
  261. foreach (var obj in batch)
  262. {
  263. if (obj.RowsData == null || obj.RowsData.Count == 0)
  264. {
  265. currentId++;
  266. continue;
  267. }
  268. foreach (var row in obj.RowsData)
  269. {
  270. sqlBuilder.Append($"(@p{paramIndex * 4}, @p{paramIndex * 4 + 1}, @p{paramIndex * 4 + 2}, @p{paramIndex * 4 + 3})");
  271. if (paramIndex < totalRows - 1)
  272. sqlBuilder.Append(", ");
  273. parameters.AddRange(new object[]
  274. {
  275. currentId,
  276. row.RowsCol,
  277. row.StartCol,
  278. row.EndCol
  279. });
  280. paramIndex++;
  281. }
  282. currentId++;
  283. }
  284. // 执行批量插入
  285. using (var cmd = new SQLiteCommand(sqlBuilder.ToString(), conn))
  286. {
  287. for (int i = 0; i < parameters.Count; i++)
  288. {
  289. cmd.Parameters.AddWithValue($"@p{i}", parameters[i]);
  290. }
  291. cmd.ExecuteNonQuery();
  292. }
  293. }
  294. // 插入RowData数据
  295. private void InsertRowData(SQLiteConnection conn, int activeObjectId, List<RowStartEndCol> rowsData)
  296. {
  297. const string insertRowData = @"
  298. INSERT INTO RowData (
  299. ActiveObjectId, RowsCol, StartCol, EndCol
  300. ) VALUES (
  301. @ActiveObjectId, @RowsCol, @StartCol, @EndCol
  302. )";
  303. using (var cmd = new SQLiteCommand(insertRowData, conn))
  304. {
  305. foreach (var row in rowsData)
  306. {
  307. cmd.Parameters.Clear();
  308. cmd.Parameters.AddWithValue("@ActiveObjectId", activeObjectId);
  309. cmd.Parameters.AddWithValue("@RowsCol", row.RowsCol);
  310. cmd.Parameters.AddWithValue("@StartCol", row.StartCol);
  311. cmd.Parameters.AddWithValue("@EndCol", row.EndCol);
  312. cmd.ExecuteNonQuery();
  313. }
  314. }
  315. }
  316. // 根据ID查询完整对象
  317. public ActiveObjectClass GetActiveObjectById(int id)
  318. {
  319. using (var conn = new SQLiteConnection(_connectionString))
  320. {
  321. conn.Open();
  322. const string query = @"
  323. SELECT
  324. ao.*,
  325. rd.Id AS RowId, rd.RowsCol, rd.StartCol, rd.EndCol
  326. FROM ActiveObject ao
  327. LEFT JOIN RowData rd ON ao.Id = rd.ActiveObjectId
  328. WHERE ao.Id = @Id";
  329. using (var cmd = new SQLiteCommand(query, conn))
  330. {
  331. cmd.Parameters.AddWithValue("@Id", id);
  332. using (var reader = cmd.ExecuteReader())
  333. {
  334. ActiveObjectClass activeObject = null;
  335. var rowsData = new List<RowStartEndCol>();
  336. while (reader.Read())
  337. {
  338. // 只初始化主对象一次
  339. if (activeObject == null)
  340. {
  341. activeObject = new ActiveObjectClass
  342. {
  343. Num = Convert.ToInt32(reader["Num"]),
  344. MinStartCol = Convert.ToInt32(reader["MinStartCol"]),
  345. MaxEndCol = Convert.ToInt32(reader["MaxEndCol"]),
  346. PreSeenLineStartCol = Convert.ToInt32(reader["LastSeenLineStartCol"]),
  347. PreSeenLineEndCol = Convert.ToInt32(reader["LastSeenLineEndCol"]),
  348. StartLine = Convert.ToInt64(reader["StartLine"]),
  349. LastSeenLine = Convert.ToInt64(reader["LastSeenLine"]),
  350. StartCheckTime = DateTime.Parse(reader["StartCheckTime"].ToString()),
  351. EndCheckTime = DateTime.Parse(reader["EndCheckTime"].ToString()),
  352. Area = Convert.ToInt32(reader["Area"]),
  353. MaxLength = Convert.ToDouble(reader["MaxLength"]),
  354. ChannelNO = Convert.ToInt32(reader["ChannelNO"]),
  355. ImageWidth = Convert.ToInt32(reader["ImageWidth"]),
  356. StateCode = Convert.ToInt32(reader["StateCode"]),
  357. BatchNumber = reader["BatchNumber"].ToString(),
  358. RowsData = rowsData
  359. };
  360. }
  361. // 添加行数据(确保RowData记录存在)
  362. if (!reader.IsDBNull(reader.GetOrdinal("RowId")))
  363. {
  364. rowsData.Add(new RowStartEndCol
  365. {
  366. RowsCol = Convert.ToInt64(reader["RowsCol"]),
  367. StartCol = Convert.ToInt32(reader["StartCol"]),
  368. EndCol = Convert.ToInt32(reader["EndCol"])
  369. });
  370. }
  371. }
  372. return activeObject;
  373. }
  374. }
  375. }
  376. }
  377. public List<string> GetAllBatchNumber()
  378. {
  379. List<string> BatchNumbers = new List<string>();
  380. using (var conn = new SQLiteConnection(_connectionString))
  381. {
  382. conn.Open();
  383. const string query = @"SELECT DISTINCT BatchNumber FROM ActiveObject";
  384. using (var cmd = new SQLiteCommand(query, conn))
  385. {
  386. using (var reader = cmd.ExecuteReader())
  387. {
  388. while (reader.Read())
  389. {
  390. BatchNumbers.Add(reader["BatchNumber"].ToString());
  391. }
  392. }
  393. }
  394. }
  395. return BatchNumbers;
  396. }
  397. public List<ActiveObjectClass> GetActiveObjectByBatchNumber(string BatchNumber)
  398. {
  399. List<ActiveObjectClass> activeObjects = new List<ActiveObjectClass>();
  400. using (var conn = new SQLiteConnection(_connectionString))
  401. {
  402. conn.Open();
  403. const string query = @"SELECT * FROM ActiveObject WHERE BatchNumber == @BatchNumber ORDER BY Id";
  404. using (var cmd = new SQLiteCommand(query, conn))
  405. {
  406. cmd.Parameters.AddWithValue("@BatchNumber", BatchNumber);
  407. using (var reader = cmd.ExecuteReader())
  408. {
  409. while (reader.Read())
  410. {
  411. object value = reader["Id"];
  412. if (!Convert.IsDBNull(value))
  413. {
  414. activeObjects.Add(new ActiveObjectClass()
  415. {
  416. Num = Convert.ToInt32(reader["Num"]),
  417. MinStartCol = Convert.ToInt32(reader["MinStartCol"]),
  418. MaxEndCol = Convert.ToInt32(reader["MaxEndCol"]),
  419. PreSeenLineStartCol = Convert.ToInt32(reader["LastSeenLineStartCol"]),
  420. PreSeenLineEndCol = Convert.ToInt32(reader["LastSeenLineEndCol"]),
  421. StartLine = Convert.ToInt64(reader["StartLine"]),
  422. LastSeenLine = Convert.ToInt64(reader["LastSeenLine"]),
  423. StartCheckTime = DateTime.Parse(reader["StartCheckTime"].ToString()),
  424. EndCheckTime = DateTime.Parse(reader["EndCheckTime"].ToString()),
  425. Area = Convert.ToInt32(reader["Area"]),
  426. MaxLength = Convert.ToDouble(reader["MaxLength"]),
  427. ChannelNO = Convert.ToInt32(reader["ChannelNO"]),
  428. ImageWidth = Convert.ToInt32(reader["ImageWidth"]),
  429. StateCode = Convert.ToInt32(reader["StateCode"]),
  430. BatchNumber = reader["BatchNumber"].ToString(),
  431. });
  432. }
  433. }
  434. }
  435. }
  436. }
  437. return activeObjects;
  438. }
  439. // 按页码获取数据
  440. public List<ActiveObjectClass> GetActiveObjectForPage(int StartLine, int EndLine)
  441. {
  442. List<ActiveObjectClass> activeObjects = new List<ActiveObjectClass>();
  443. try
  444. {
  445. using (var conn = new SQLiteConnection(_connectionString))
  446. {
  447. conn.Open();
  448. const string query = @"
  449. SELECT
  450. ao.*,
  451. rd.Id AS RowId, rd.RowsCol, rd.StartCol, rd.EndCol
  452. FROM ActiveObject ao
  453. LEFT JOIN RowData rd ON ao.Id = rd.ActiveObjectId
  454. WHERE ao.StartLine <= @StartLine AND LastSeenLine>=@LastSeenLine ORDER BY rd.Id";
  455. using (var cmd = new SQLiteCommand(query, conn))
  456. {
  457. cmd.Parameters.AddWithValue("@StartLine", EndLine);
  458. cmd.Parameters.AddWithValue("@LastSeenLine", StartLine);
  459. using (var reader = cmd.ExecuteReader())
  460. {
  461. int NowId = -1;
  462. ActiveObjectClass activeObject = null;
  463. var rowsData = new List<RowStartEndCol>();
  464. while (reader.Read())
  465. {
  466. object value = reader["Id"];
  467. if (!Convert.IsDBNull(value))
  468. {
  469. if (NowId != Convert.ToInt32(reader["Id"]))
  470. {
  471. if (activeObject != null)
  472. {
  473. activeObjects.Add(activeObject);
  474. activeObject = null;
  475. rowsData = new List<RowStartEndCol>();
  476. }
  477. NowId = Convert.ToInt32(reader["Id"]);
  478. }
  479. // 只初始化主对象一次
  480. if (activeObject == null)
  481. {
  482. activeObject = new ActiveObjectClass
  483. {
  484. Num = Convert.ToInt32(reader["Num"]),
  485. MinStartCol = Convert.ToInt32(reader["MinStartCol"]),
  486. MaxEndCol = Convert.ToInt32(reader["MaxEndCol"]),
  487. PreSeenLineStartCol = Convert.ToInt32(reader["LastSeenLineStartCol"]),
  488. PreSeenLineEndCol = Convert.ToInt32(reader["LastSeenLineEndCol"]),
  489. StartLine = Convert.ToInt64(reader["StartLine"]),
  490. LastSeenLine = Convert.ToInt64(reader["LastSeenLine"]),
  491. StartCheckTime = DateTime.Parse(reader["StartCheckTime"].ToString()),
  492. EndCheckTime = DateTime.Parse(reader["EndCheckTime"].ToString()),
  493. Area = Convert.ToInt32(reader["Area"]),
  494. MaxLength = Convert.ToDouble(reader["MaxLength"]),
  495. ChannelNO = Convert.ToInt32(reader["ChannelNO"]),
  496. ImageWidth = Convert.ToInt32(reader["ImageWidth"]),
  497. StateCode = Convert.ToInt32(reader["StateCode"]),
  498. BatchNumber = reader["BatchNumber"].ToString(),
  499. RowsData = rowsData
  500. };
  501. }
  502. // 添加行数据(确保RowData记录存在)
  503. rowsData.Add(new RowStartEndCol
  504. {
  505. RowsCol = Convert.ToInt64(reader["RowsCol"]),
  506. StartCol = Convert.ToInt32(reader["StartCol"]),
  507. EndCol = Convert.ToInt32(reader["EndCol"])
  508. });
  509. }
  510. }
  511. if (activeObject != null)
  512. {
  513. activeObjects.Add(activeObject);
  514. activeObject = null;
  515. rowsData = new List<RowStartEndCol>();
  516. }
  517. }
  518. }
  519. }
  520. }
  521. catch(Exception ex)
  522. {
  523. Console.WriteLine($"GetActiveObjectForPage - Error:{ex.Message}");
  524. }
  525. return activeObjects;
  526. }
  527. public void GetAllActionMinStartMaxEndLine(out int Num, out int StartLine, out int EndLine)
  528. {
  529. using (var conn = new SQLiteConnection(_connectionString))
  530. {
  531. conn.Open();
  532. const string query = @"
  533. SELECT MAX(Num) AS Num, MAX(LastSeenLine) AS MaxLastSeenLine, MIN(StartLine) AS MinStartLine FROM ActiveObject";
  534. int MinStartLine = 0;
  535. int MaxLastSeenLine = 0;
  536. int StartNum = 0;
  537. using (var cmd = new SQLiteCommand(query, conn))
  538. {
  539. using (var reader = cmd.ExecuteReader())
  540. {
  541. while (reader.Read())
  542. {
  543. object value = reader["MinStartLine"];
  544. if (!Convert.IsDBNull(value))
  545. {
  546. MinStartLine = Convert.ToInt32(reader["MinStartLine"]);
  547. MaxLastSeenLine = Convert.ToInt32(reader["MaxLastSeenLine"]);
  548. StartNum = Convert.ToInt32(reader["Num"]);
  549. }
  550. }
  551. }
  552. }
  553. StartLine = MinStartLine;
  554. EndLine = MaxLastSeenLine;
  555. Num = StartNum;
  556. }
  557. }
  558. // 根据Num查询ID
  559. public int GetActiveIdByNum(int Num)
  560. {
  561. int result = -1;
  562. using (var conn = new SQLiteConnection(_connectionString))
  563. {
  564. conn.Open();
  565. const string query = @"
  566. SELECT * FROM ActiveObject WHERE Num = @Num";
  567. using (var cmd = new SQLiteCommand(query, conn))
  568. {
  569. cmd.Parameters.AddWithValue("@Num", Num);
  570. using (var reader = cmd.ExecuteReader())
  571. {
  572. var rowsData = new List<RowStartEndCol>();
  573. while (reader.Read())
  574. {
  575. object value = reader["Id"];
  576. if (!Convert.IsDBNull(value))
  577. {
  578. result = Convert.ToInt32(reader["Id"]);
  579. }
  580. }
  581. }
  582. }
  583. }
  584. return result;
  585. }
  586. public List<ActiveObjectClass> GetAllErrorAction()
  587. {
  588. List<ActiveObjectClass> activeObjects = new List<ActiveObjectClass>();
  589. try
  590. {
  591. using (var conn = new SQLiteConnection(_connectionString))
  592. {
  593. conn.Open();
  594. const string query = @"
  595. SELECT
  596. ao.*,
  597. rd.Id AS RowId, rd.RowsCol, rd.StartCol, rd.EndCol
  598. FROM ActiveObject ao
  599. LEFT JOIN RowData rd ON ao.Id = rd.ActiveObjectId
  600. WHERE ao.StateCode != 0";
  601. using (var cmd = new SQLiteCommand(query, conn))
  602. {
  603. using (var reader = cmd.ExecuteReader())
  604. {
  605. int NowId = -1;
  606. ActiveObjectClass activeObject = null;
  607. var rowsData = new List<RowStartEndCol>();
  608. while (reader.Read())
  609. {
  610. object value = reader["Id"];
  611. if (!Convert.IsDBNull(value))
  612. {
  613. if (NowId != Convert.ToInt32(reader["Id"]))
  614. {
  615. if (activeObject != null)
  616. {
  617. activeObjects.Add(activeObject);
  618. activeObject = null;
  619. rowsData = new List<RowStartEndCol>();
  620. }
  621. NowId = Convert.ToInt32(reader["Id"]);
  622. }
  623. // 只初始化主对象一次
  624. if (activeObject == null)
  625. {
  626. activeObject = new ActiveObjectClass
  627. {
  628. Num = Convert.ToInt32(reader["Num"]),
  629. MinStartCol = Convert.ToInt32(reader["MinStartCol"]),
  630. MaxEndCol = Convert.ToInt32(reader["MaxEndCol"]),
  631. PreSeenLineStartCol = Convert.ToInt32(reader["LastSeenLineStartCol"]),
  632. PreSeenLineEndCol = Convert.ToInt32(reader["LastSeenLineEndCol"]),
  633. StartLine = Convert.ToInt64(reader["StartLine"]),
  634. LastSeenLine = Convert.ToInt64(reader["LastSeenLine"]),
  635. StartCheckTime = DateTime.Parse(reader["StartCheckTime"].ToString()),
  636. EndCheckTime = DateTime.Parse(reader["EndCheckTime"].ToString()),
  637. Area = Convert.ToInt32(reader["Area"]),
  638. MaxLength = Convert.ToDouble(reader["MaxLength"]),
  639. ChannelNO = Convert.ToInt32(reader["ChannelNO"]),
  640. ImageWidth = Convert.ToInt32(reader["ImageWidth"]),
  641. StateCode = Convert.ToInt32(reader["StateCode"]),
  642. BatchNumber = reader["BatchNumber"].ToString(),
  643. RowsData = rowsData
  644. };
  645. }
  646. // 添加行数据(确保RowData记录存在)
  647. rowsData.Add(new RowStartEndCol
  648. {
  649. RowsCol = Convert.ToInt64(reader["RowsCol"]),
  650. StartCol = Convert.ToInt32(reader["StartCol"]),
  651. EndCol = Convert.ToInt32(reader["EndCol"])
  652. });
  653. }
  654. }
  655. if (activeObject != null)
  656. {
  657. activeObjects.Add(activeObject);
  658. activeObject = null;
  659. rowsData = new List<RowStartEndCol>();
  660. }
  661. }
  662. }
  663. }
  664. }
  665. catch (Exception ex)
  666. {
  667. Console.WriteLine($"GetActiveObjectForPage - Error:{ex.Message}");
  668. }
  669. return activeObjects;
  670. }
  671. // 关闭定时器并释放资源
  672. public void Dispose()
  673. {
  674. _timer?.Dispose();
  675. FlushData(null); // 确保最后一批数据被写入
  676. }
  677. }
  678. }