【问题标题】:Can TStringField be created with dynamic Size?可以使用动态大小创建 TStringField 吗?
【发布时间】:2014-07-02 11:29:42
【问题描述】:

我在TClientDataset 和TStringField 字段中出现Insufficient memory 错误。我需要使用从 0 到 8000 的字符串长度 - 但在填写 TClientDataset 之前不知道长度是多少。

那么,TStringField 可以用动态的Size 创建吗?

附:最初的任务是将 TDBGrid 复制到 TClientDataset。

【问题讨论】:

  • 问题不在于 TClientDataSet 是否可以为其从其提供者读取的记录分配可变大小的缓冲区等,因为它必须大量分配这些缓冲区?答案是肯定的,这将是令人惊讶的。由于(在 D7 中)函数 TCustomClientDataSet.AllocRecordBuffer: PChar; 在我看来不太可能开始结果 := AllocMem(FRecBufSize);结尾; - 但这是虚拟的,所以你总是可以编写自己的自定义后代。
  • 根据我从您那里看到的与此相关的两个问题,我认为您正在尝试以非常不正确的方式使用 CDS。如果您使用 CDS 的设计用途,则不会出现您所询问的任何问题。恐怕我不知道你想要完成什么,因为你所描述的只是它出了问题的事情。
  • Ken,问题很简单:Size = 8000 的 TStringField 过多会引发 Insufficient memory 错误。我对所有组件的使用完全符合客户的任务。
  • 请不要因为内存不足而将您的问题标记为“内存泄漏”。
  • 嗯...它可以完成“客户的任务”,但这并不意味着您选择了正确的类来执行此操作(或正确使用它)。我可以用锤子完成打螺丝的任务;仅仅因为我可以让它工作并不意味着它是这样做的正确方法。

标签: delphi tclientdataset tstringfield


【解决方案1】:

您在这些字段中存储哪些类型的数据需要最多 8000 个字符?

假设您使用通配符对这些字段进行部分搜索。我敢打赌,这样的搜索需要很长时间,甚至可能使您的数据库服务器崩溃。

除了并非所有数据库表都支持 8192 字符大小的字符串字段。

http://docwiki.embarcadero.com/Libraries/XE6/en/Data.DB.TStringField

TStringField 封装了字段共有的基本行为 包含字符串数据。字符串字段的值在物理上是 存储为最多 8192 个字符的序列。但是,有些表 类型可能只支持较小尺寸的字符串字段。

那么您为什么不使用 TMemoFields 来代替,因为它们允许文本的动态大小? http://docwiki.embarcadero.com/Libraries/XE6/en/Data.DB.TMemoField

【讨论】:

  • Fwiw MS Sql Server 即使在 2000 版本中也允许 4000 字符/8000 字节的 unicode 字符字段。 Istr 表示可以索引前 900 个字节。此外,TDataSet 将 TMemoField 视为 TBlobField 的特例,需要为每个 AsString 访问创建/释放 TBlobStream!
  • +1 - 但这听起来确实像一个数据库设计问题,这正是您所暗示的。
  • 是的,我指的是这种可能性。但为了确保我问了一个问题,即他存储了哪些数据才能需要 8000 个字符长的字符串。
  • 您是否在此处打印了其他问题的答案?我没有看到任何相关信息。
  • 不,我没有。也许您看不到我的回答与您的问题有何关联,因为我正在开箱即用,因此考虑了替代方法。在您的问题中,您问是否可以拥有动态大小的 StringFields。答案是否定的,因为 StringFields 是固定长度的数据字段。并且它们的大小必须至少是您尝试保存在其中的数据的最大大小,即使它仅用于一条记录。所以我建议使用类似于 TStringList 的 TMemo 字段,但它的大小实际上取决于您存储在其中的数据量。
【解决方案2】:

我使用了以下解决方案。首先,根据Length(aDBGrid.Columns[i].Field.DisplayText) 计算最大值Sizes。然后用计算出的Sizes创建TStringFields。

附:最初的任务是将 TDBGrid 复制到 TClientDataset。

【讨论】:

  • 你是什么意思 - “长度(TStringField)”?如果您至少有一个大小为 8kb 的项目,那么即使所有其他项目都很小,您也会再次遇到同样的问题。所以这不是一个解决方案。
  • 更不用说 Length(TStringField) 不会告诉你给定实例的字符串长度。
  • 抱歉打印错误,已修复。至少一项大小为 8kb 的项目不会出现在非字符串字段上。字符串字段的大量内存使用取决于 Embarcadero 代码。
  • 正如 Ken White 在对您最初的问题的评论中提到的那样,我认为您没有正确使用可用的工具,并且做出的假设根本不正确。
  • -0.5 你为什么要通过 TBGrid 的列访问数据集的字段,为什么不通过数据集访问它们呢?这是一个等待发生的意外 - 不一定是现在,但最终可能会有数据集的字段未绑定到网格列。当然,SO 的答案是为了未来的读者。
猜你喜欢
  • 1970-01-01
  • 2015-09-30
  • 2010-09-05
  • 1970-01-01
  • 1970-01-01
  • 2011-03-29
  • 2021-09-15
  • 1970-01-01
  • 2019-03-01
相关资源
最近更新 更多