Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果不推荐使用ShortString,那么限制字符串长度的最佳方法是什么_String_Delphi_Field - Fatal编程技术网

如果不推荐使用ShortString,那么限制字符串长度的最佳方法是什么

如果不推荐使用ShortString,那么限制字符串长度的最佳方法是什么,string,delphi,field,String,Delphi,Field,有这样的记录并不罕见: TAddress = record Address: string[50]; City : string[20]; State : string[2]; ZIP : string[5]; end; 有硬编码字符串大小以确保字符串的大小不会超过为数据分配的数据库字段大小是很好的 然而,鉴于ShortString类型已被弃用,Delphi开发人员如何“解决”这个问题?将记录字段声明为string可以完成作业,但不能保护数据不超过适当的长度 这里最

有这样的记录并不罕见:

TAddress = record
  Address: string[50];
  City   : string[20];
  State  : string[2];
  ZIP    : string[5];
end;
有硬编码字符串大小以确保字符串的大小不会超过为数据分配的数据库字段大小是很好的

然而,鉴于
ShortString
类型已被弃用,Delphi开发人员如何“解决”这个问题?将记录字段声明为
string
可以完成作业,但不能保护数据不超过适当的长度


这里最好的解决方案是什么?

如果我必须防止数据超过正确的长度,我会让数据库代码尽可能多地处理它。对字段设置大小限制,并在数据绑定控件中向用户显示数据。绑定到字符串字段的
TDBEdit
将正确执行长度限制。将其设置为直接从数据集填充记录,并且记录的长度始终正确


然后,您需要担心的是数据从一些外部源进入记录,而这些外部源不属于您的UI。为此,请使用相同的过程。让导入代码将数据插入数据集中,并让其长度约束为您进行验证。如果引发异常,请拒绝导入。如果没有,那么您就得到了一个有效的数据集行,可以用来填充记录。

问题中的短字符串类型并不能真正防止字符串超过适当的长度。当您为这些短字符串指定较长的值时,该值会自动截断

我不确定您使用的是哪种数据库访问方法,但我认为它也会做同样的事情。即将任何超长字符串截断为最大长度。在这种情况下,没有什么可做的

如果您的数据库访问方法在指定超长字符串时抛出错误,则需要在将值传递给数据库之前进行截断

如果您必须显式地截断,那么在很多地方您可能会选择这样做。我的原则是在最后一刻截短。这就是你受到限制的点。截断其他任何地方似乎都是错误的。这意味着数据库限制正在扩展到代码中与数据库不明显相关的部分


当然,所有这些都是基于这样一个假设,即您希望进行静默截断。如果你想在截短的情况下提供用户反馈,那么你需要决定在哪里采取正确的措施来处理这些反馈。

根据我的理解,我的答案应该是“不要混合层”

我怀疑字符串长度是在数据库层级别(列宽)或业务应用程序层指定的(例如,验证卡号)

从“纯Delphi代码”的角度来看,您不应该知道您的
字符串
变量具有最大长度,除非您到达持久层甚至业务层

使用属性可能是一个想法。但它可能会“污染”源代码,原因与混合层的原因完全相同


因此,我建议使用专用的数据建模,在其中指定数据期望。然后,在Delphi
var
级别,您只需定义一个普通的
字符串
。这正是我们的mORMot框架:在模型级别,有一些专用类-方便、可扩展和干净。

我遇到了这个问题-严重-从Delphi 6升级到2009对于一个程序正在/正在做的事情,必须能够将旧的ASCII字符串作为单个ASCII字符处理

该程序输出ASCII文件(甚至没有ANSI文件),并有一些概念,例如在最后一个数字上过冲以表示负数。所以文件格式可以说有点倒退了

在2009年第一次构建之后(10年前的代码,好吧,你不知道!)在对单元名称进行排序之后,出现了数百个报告的错误/非法分配和数据丢失/转换警告


无论Delphi的后台操作/字符串和字符的魔法有多好,我都不够信任它。最后,为了确保一切恢复原样,我将它们全部重新声明为字节数组,然后相应地更改了代码。

如果您只是从Delphi 7移植到XE3,请保留它。此外,尽管“ShortString”可能会被弃用,但如果他们完全删除它,我会大发雷霆,因为如果没有它,很多代码将永远无法重建。ShortString+Records仍然是指定面向字节的记录数据存储文件的唯一实用方法。Delphi永远不会删除短字符串,也不会改变其行为,这将对现有的Delphi代码造成破坏。所以,如果您真的必须定义记录并限制其长度,并且您真的不希望这些记录支持Unicode,那么就没有理由停止使用或停止编写短字符串代码。也就是说,我讨厌短字符串和记录文件,希望它们能消失,并且很高兴它们被标记为不推荐使用

尽管如此,我完全同意梅森和大卫的观点;我想说的是,长度检查和验证是表示/验证方面的问题,而Delphi强大的键入功能并不是处理这些问题的正确位置或方法。如果需要对类设置验证约束,请编写实现约束存储的帮助器类(EmployeeName是字符串字段,EmployeeName具有以下长度限制)。例如,在编辑控件中,这已经是一个属性。在我看来,使用新的绑定系统将DB字段映射到可视字段比试图在代码中静态地表示约束要好得多

用户输入验证和存储是不同的,长度限制应该在GUI控件中设置,而不是在数据结构中设置

你可以举我们为例
TTestRecordProp = record
private
  FField20: string;
  ...
  FFieldN: string
  procedure SetField20(const Value: string);
public
  property Field20: string read FField20 write SetField20;
  ...
  property FieldN: string ...
end;
...
procedure TTestRecordProp.SetField20(const Value: string);
begin
  if Length(Value) > 20 then
    /// maybe raise an exception?
    FField20 := Copy(FField20, 1, 20)
  else
    FField20 := Value;
end;
TTestRecordEnsureLengths = record
  Field20: string;
  procedure EnsureLengths;
end;
...
procedure TTestRecordEnsureLengths.EnsureLengths;
begin
  // for each string field, test it's length and truncate or raise exception
  if Length(Field20) > 20 then
    Field20 := Copy(Field20, 1, 20); // or raise exception...
end;