大佬教程收集整理的这篇文章主要介绍了delphi – 在const数组中传递通用记录,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我想使用ALLEN Bauer的Nullable记录在一种自制的ORM中使用“Plain Old Delphi Objects”来映射数据库行:
type Nullable<T> = record ... end; TmyTabLeobject = class(TDbOject) private FId: Integer; FOptionalField: Nullable<String>; protected procedurE internalSave; override; public property Id: Integer read FId write SetId; property OptionalField: Nullable<String> read FOptionalField write SetOptionalField; end; ... implementation procedure TmyTabLeobject.InternalSave; begin { FDbController is declared and managed in TDbObject,it contains fonction to run queries on the database } FDbController.Execute( 'update or insert into MY_TABLE(TABLE_ID,OPTIONAL_FIELD) ' + 'values (?,?) ' + 'matching(TABLE_ID) returning TABLE_ID',[FId,FOptionalField],procedure (Fields: TSQLResult) begin FId := Fields.AsInteger[0]; end; end; end;@H_450_5@上面的代码导致错误:“E2250:没有覆盖版本的”执行“函数可以用这些参数调用”(翻译自法语:E2250 Aucuneversionsurchargéede’Execute’nepeutêtreaposléeavecces arguments)
我可以显式地将FOptionalField转换为字符串或其他任何东西,因为Nullable会覆盖ad-hoc运算符,但我真的必须知道Nullable是否有值,直到我将const数组映射到数据库查询对象的Params字段:
procedure TDbContext.MapParams(Q: TUIBQuery; Params: TConstArray); const BOOL_STR: arraY[Boolean] of String = ('F','V'); var i: Integer; begin for i := 0 to High(Params) do case Params[i].VType of vtInteger : Q.Params.AsInteger[i] := Params[i].VInteger; vTint64 : Q.Params.AsInt64[i] := Params[i].VInt64^; vtBoolean : Q.Params.AsString[i] := BOOL_STR[Params[i].VBoolean]; vtChar : Q.Params.AsAnsiString[i] := Params[i].VChar; vtWideChar: Q.Params.AsString[i] := Params[i].VWideChar; vtExtended: Q.Params.AsDouble[i] := Params[i].VExtended^; vtCurrency: Q.Params.AsCurrencY[i] := Params[i].VCurrency^; vtString : Q.Params.AsString[i] := String(Params[i].VString^); vtPChar : Q.Params.AsAnsiString[i] := Params[i].VPChar^; vtAnsiString: Q.Params.AsAnsiString[i] := AnsiString(Params[i].VAnsiString); vtWideString: Q.Params.AsUnicodeString[i] := PWideChar(Params[i].VWideString); vtVariant : Q.Params.AsVariant[i] := Params[i].VVariant^; vtUnicodeString: Q.Params.AsUnicodeString[i] := String(Params[i].VUnicodeString); vtPointer : begin if Params[i].VPointer = nil then Q.Params.IsNull[i] := True else Assert(false,'not nil pointer is not supported'); end else Assert(false,'not supported'); end; end;@H_450_5@你对如何使这种结构成为可能有任何想法吗?我找到了一种方法,通过使用RTTI在Nullable中向Variant添加显式的转换操作符覆盖,但这有点棘手,因为它需要在const调用数组中显式转换为Variant:
class operator Nullable<T>.Explicit(Value: Nullable<T>): Variant; begin if Value.HasValue then Result := TValue.From<T>(Value.value).AsVariant else Result := Null; end; ... FDbController.Execute( 'update or insert into MY_TABLE(TABLE_ID,Variant(FOptionalField)],procedure (Fields: TSQLResult) begin FId := Fields.AsInteger[0]; end; end;@H_450_5@
实际上,TVarRec.VType值没有任何vtRecord.
Variant类型本身没有Delphi处理的varRecord类型. Windows世界中存在这样的变体类型(例如,DotNet结构映射到COM中的vt_Record类型),但这种变体不是由Delphi处理的.
可能的是将指针传递给记录的typeinfo,然后传递给记录:
case Params[i].VType of vtPointer: if (i<high(Params)) and (Params[i+1].VType=vtPointer) then if Params[i].VPointer = TypeInfo(MyRecord) then begin ... end;@H_450_5@也许这是一个不太好的答案,因为你使用泛型…但至少是一个开始…在所有情况下,这就是我如何使用预先通用的Delphi编译器. TypeInfo()关键字已经非常强大,并且比“新”RTTI实现更快.
另一种可能性(与泛型兼容)应该是在记录内容中添加一些记录类型ID.然后将记录作为指针传递,读取ID,并按预期使用它:
case Params[i].VType of vtPointer: if Params[i].VPointer <> nil then case PRecordType(Params[i].VPointer)^ of aRecordType: ... ... end;@H_450_5@这可以通过简单地扩展Nullable< T>的初始值来实现.定义.
后Scriptum:
在ORM中使用记录可能不是最好的解决方案……
类模型比Delphi中的记录/对象模型更先进,并且因为ORM是关于对象建模的,所以你应该使用最好的OOP模型,恕我直言.通过依赖类而不是记录,您可以拥有继承,嵌入式类型信息(通过Class方法或仅通过PPointer(aObject)^),可空值和虚方法(这对于ORM非常方便).即使const参数数组问题也会允许直接处理这样的vtObject类型,以及专用的类虚方法.基于记录的ORM只是序列化表行的一种方式,而不是使用OOP最佳实践设计应用程序.关于性能,与复制记录的潜在问题相比,类实例的内存分配不是问题(_CopyRecord RTL函数 – 由编译器以隐藏方式调用,例如函数参数-can be very slow).
例如,在我们的ORM中,我们handle dynamic array properties,even dynamic arrays of records in properties(Delphi不为已发布的记录属性生成RTTI,这是当前类实现的另一个不一致行为).我们使用“旧”RTTI将records and dynamic arrays序列化为JSON或二进制,并且它运行良好.最好的两个对象世界.
以上是大佬教程为你收集整理的delphi – 在const数组中传递通用记录全部内容,希望文章能够帮你解决delphi – 在const数组中传递通用记录所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。