FireDAC注意事项

** FDConnection **

1,

FDConnection.FetchOptions.Cache = [fiBlobs,fiDetails], 如果里面包含 fiMeta, 在不断开连接的情况下, FDStoredProc 的参数在刷新后,如果有修改存储过程的参数, 则再执行 FDStoredProc.Prepare ;时,还是取得的原来的参数, 原因在于:将此存储过程原有的参数已经进行了缓存

2.

FDConnection.FetchOptions.Items.Cache = [fiBlobs,fiDetails], 如果里面 不 包含 fiMeta,则 FDStoredProc.Prepare 后, 取不到存储过程参数


******************** 代码  ****************************

var
  mParam : TFDParam ;
  i: Integer ;
begin
  if NOT FDCon.Connected then
  begin
    FDCon.ConnectionString := edt_FDConStr.Text ;
    FDCon.Connected := true ;
  end ;
  FDSP.Close ;
  FDSP.Params.Clear ;
  FDSP.StoredProcName := '' ; 
  FDSP.StoredProcName := 'Z_USP_WicherTest' ;
  mParam := FDSP.Params.Add ;
  with mParam do
  begin
    Name := '@T1' ;
    DataType := ftString ;
    //FDDataType := dtString ;
    ParamType := ptInput ;
    Size := 50 ;
    Precision := 0 ;
    NumericScale := 0 ;
    Value := 'A' ;
  end;
  FDSP.Open();
  FDSp.First ;
  while NOT FDSp.Eof do
  begin
    mm_XECode.Lines.Add('记录: ' + FDSp.RecNo.ToString()) ;
    for i := 0 to FDSp.FieldCount - 1 do
    begin
      mm_XECode.Lines.Add(FDSp.Fields[i].FieldName+ ':' + VarToStr(FDSp.Fields[i].Value)) ;
    end;
    FDSp.Next ;
  end;

  // FDSP.Disconnect(True);   -- A
  // FDSP.Close ;                    -- B
  // 以上A与B语句都不要,下面OPEN后, 还是原来的结果,实际传入参数值B,应该是另一个表的数据
  // 如果只留下B,则OPEN后,字段为原A的字段,但数据又是从B表中取的
  // 如果留下A, 则OPEN正常, 为B表的字段与数据

  FDSP.Params.ParamByName('@T1').Value := 'B' ;
  FDSP.Open();
  FDSp.First ;
  while NOT FDSp.Eof do
  begin
    mm_XECode.Lines.Add('记录: ' + FDSp.RecNo.ToString()) ;
    for i := 0 to FDSp.FieldCount - 1 do
    begin
      mm_XECode.Lines.Add(FDSp.Fields[i].FieldName+ ':' + VarToStr(FDSp.Fields[i].Value)) ;
    end;
    FDSp.Next ;
  end;

3. FDConnection的连接
最终是调用 FireDAC.Phys.ODBCWrapper.pas里面的 DriverConnec
function TODBCConnection.DriverConnect(const AConnString: String;
  ADriverCompletion: SQLUSmallint; AParentWnd: SQLHWnd): String;
begin
...
  Check(Lib.SQLDriverConnect(FHandle, AParentWnd, PSQLChar(AConnString), SQL_NTS,
    PSQLChar(Result), C_RETURNED_STRING_MAXLEN, iOutConnStrLen, ADriverCompletion));
...
end;

TSQLDriverConnect定义:
  TSQLDriverConnect = function(
    HDbc:              SQLHDbc;
    hwnd:              SQLHWnd;
    szConnStrIn:       PSQLChar;
    cbConnStrIn:       SQLSmallint;
    szConnStrOut:      PSQLChar;
    cbConnStrOutMax:   SQLSmallint;
    var pcbConnStrOut: SQLSmallint;
    fDriverCompletion: SQLUSmallint
    ): SQLReturn; {$IFDEF MSWINDOWS} stdcall {$ELSE} cdecl {$ENDIF};

调用的ODBC, 对应详细说明见MS官网:
https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqldriverconnect-function

4.  FDConnection 连接 MSSQL时,此语句无法避免
   SELECT SCHEMA_NAME(), DATABASEPROPERTYEX('Express_MLG', 'COLLATION')
   原因在于: FireDAC.Phys.MSSQL.pas
    if oConnMeta.ServerVersion >= svMSSQL2005 then
      oStmt.Open(1, 'SELECT SCHEMA_NAME(), ' + sCollProp)
    else
      oStmt.Open(1, 'SELECT USER_NAME(), ' + sCollProp);

  此句不知道如何避免:因为 Lib.SQLDriverConnect时,调用了ODBC驱动造成,应该与不同的驱动有关
   select 504,c.name,c.description,c.definition from master.dbo.syscharsets c where c.id = convert(tinyint, databasepropertyex ( db_name() , 'sqlcharset'))

  以上两句暂时避免不了,加上程序一般不可能没事就断开连接再接上连接,所以对SQL Server性能影响可忽略


5. FDConnection.FetchOptions.Mode :  (fmManual, fmOnDemand, fmAll, fmExactRecsMax)
  写了一个MS SQL存储过程来取数据, 因为在存储过程里面写了分页语句,所以加了一个输出参数来送出总记录数,通过FDConnection 与 FDStoredProc 来操作时,
能得到数据,但输出参数值总是得不到,后不断调试,发现只是把存储过程里面的表名替换一下, 有时能得到, 有时又得不到,崩溃中。
使用MSSQL的事件探查器,调试发现向ODBC提交指令后,当时没有监控到语句,不知道什么操作后才出来, 推测FireDAC进行了延时处理,在查看源码的过程中, 有使用了异步执行的代码,运用了线程。后没办法,再官网查看FDConnection一个个属性说明, 看到了: FetchOptions.Mode, 默认值给的是 fmOnDemand, 对此的官方解释为:
The records are fetched automatically by FireDAC, when they are demanded by the navigation or other dataset methods. At each demand, FireDAC fetches one or more record sets, containing RowsetSize records. This mode allows you to open big result sets without a significant delay, as it happens with the fmAll mode. But the total amount of time of fetching all the records will be higher than in the fmAll mode. For example, on the Microsoft SQL Server, the server side static cursor will be used . 
后试着调整为: fmAll, 成功得到了输出参数的值, 对fmAll的说明为:

All result set records are fetched automatically by FireDAC at the dataset Open call. On a big result set, it may take some time, but the navigation through a dataset will be fast, because all records will be stored in a FireDAC internal data storage. For many DBMSs, such as a Microsoft SQL Server, MySQL Server, Sybase SQL Anywhere:

  • It releases a client result set buffer and allows you to execute the next command returning result sets.
  • Gives maximum fetch performance. For example, on Microsoft SQL Server, the fast forward-only cursor will be used
英文不好,为不影响看官的判断,自己翻译理解,原文出处: http://docwiki.embarcadero.com/Libraries/Berlin/en/FireDAC.Stan.Option.TFDFetchOptions.Mode
困绕了1.5天的问题终于得到解决

6. SQL Server中的 datetime 对应 fd 的 ftTimeStamp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值