restful 服务器一个问题,看ChatGPT的威力 (续2)
实际上Pascal是一个非常优美的语言。只是仁者见仁智者见智。
我们一直埋怨,而不是埋怨自己。说到底:功力不够。想短平快,功底又不够,这就是挑战。
datasnap很复杂,但是又很简单。写了够小的破restful服务程序,动不动出问题。
在多次交流中,你会不断理解和提高。
# Delphi + REST + 多线程数据库连接规范清单 ## 🎯 目标 短连接、线程安全、资源无泄漏、TCP 不挂起 --- ## 1️⃣ 连接创建原则 - 所有方法中**禁止使用组件字段** `FDConnection1` 直接执行查询 - **统一使用局部变量**:`LConn: TFDConnection` - 建议封装工具函数统一创建连接:`CreateLocalFDConnectionFromTemplate` --- ## 2️⃣ 安全连接参数设置 ```pascal LConn := TFDConnection.Create(nil); LConn.LoginPrompt := False; LConn.Params.Assign(FDConnection1.Params); LConn.Params.Pooled := False; LConn.Connected := True; ``` --- ## 3️⃣ 查询/操作对象规则 ```pascal LQuery := TFDQuery.Create(nil); LQuery.Connection := LConn; ``` 不要使用设计时组件字段,如 `FDQuery1`, `FDCommand1`。 --- ## 4️⃣ 释放规则(必须使用 try..finally) ```pascal try // 操作 finally if LConn.Connected then LConn.Close; LConn.Free; end; ``` 如使用账套切换: ```pascal FDManager.CloseConnectionDef(LConn.ConnectionDefName); ``` --- ## 5️⃣ 多线程场景特殊规则 - 所有数据库对象(连接、查询)必须是**局部变量** - 禁止在线程中访问 `FDConnection1` 组件字段 - 使用 `TTask`, `TThread`, `TEvent`, `TInterlocked` 做线程同步 - 使用 `PostLog` 记录连接耗时及释放日志 --- ## 6️⃣ 调试建议 ```pascal FDManager.Tracing := True; FDManager.TraceFileName := 'FDTrace.log'; ``` 查询 SQL Server 当前连接: ```sql SELECT * FROM sys.dm_exec_connections WHERE session_id <> @@SPID; ``` 查看连接数: ```pascal ShowMessage(IntToStr(FDManager.ActiveConnections)); ``` --- ## 7️⃣ REST 方法封装建议 ```pascal function GetFDJSONDatasets(aSqlExpr: string): TFDJSONDatasets; var LConn: TFDConnection; LQuery: TFDQuery; begin LConn := CreateLocalFDConnectionFromTemplate(FDConnection1); try LQuery := TFDQuery.Create(nil); try LQuery.Connection := LConn; LQuery.SQL.Text := aSqlExpr; LQuery.Open; Result := TFDJSONDataSetsWriter.WriteDataSets([LQuery]); finally LQuery.Free; end; finally if LConn.Connected then LConn.Close; LConn.Free; end; end; ``` --- ## 推荐封装函数 ```pascal function CreateLocalFDConnectionFromTemplate(BaseConn: TFDConnection): TFDConnection; begin Result := TFDConnection.Create(nil); Result.LoginPrompt := False; Result.Params.Assign(BaseConn.Params); Result.Params.Pooled := False; Result.Connected := True; end; ``` --- ## ✅ 结语 > 短连接 REST 服务的本质是:**每次来一个连接,用完立即释放,绝不残留。**