5

次のような記録を持つことは珍しくありません。

TAddress = record
  Address: string[50];
  City   : string[20];
  State  : string[2];
  ZIP    : string[5];
end;

文字列のサイズが、データに割り当てられたデータベース フィールドのサイズを超えないようにするために、文字列のサイズをハードコードした方がよい場合があります。

しかし、ShortString型が非推奨になったことを考えると、Delphi 開発者はこの問題を「解決」するために何をしているのでしょうか? レコード フィールドを as として宣言するstringと、作業は完了しますが、データが適切な長さを超えないようにすることはできません。

ここでの最善の解決策は何ですか?

4

6 に答える 6

5

データが適切な長さを超えないようにする必要がある場合は、可能な限りデータベース コードに処理させます。フィールドにサイズ制限を設け、データ バインド コントロールでユーザーにデータを表示します。文字列フィールドにバインドするTDBEditと、長さ制限が正しく適用されます。レコードがデータセットから直接入力されるように設定すると、常に適切な長さになります。

その後、心配する必要があるのは、UI の一部ではない外部ソースからレコードに入ってくるデータだけです。そのためには、同じプロセスを使用します。インポート コードでデータをデータセットに挿入し、その長さの制約で検証を行います。例外が発生した場合は、インポートを拒否します。そうでない場合は、レコードの入力に使用できる有効なデータセット行があります。

于 2012-12-17T17:02:50.517 に答える
5

質問の短い文字列タイプは、文字列が適切な長さを超えないように実際には保護しません。これらの短い文字列に長い値を割り当てると、値は暗黙のうちに切り捨てられます。

どのデータベース アクセス方法を使用しているかはわかりませんが、同じことをすると思います。つまり、長すぎる文字列を切り捨てて最大長にします。その場合、何もすることはありません。

データベース アクセス メソッドに長すぎる文字列を指定するとエラーがスローされる場合は、値をデータベースに渡す前に切り詰める必要があります。

明示的に切り詰める必要がある場合は、そうする場所がたくさんあります。私の哲学は、可能な限り最後の瞬間に切り捨てることです。それはあなたが制限を受けるポイントです。他の場所を切り捨てるのは間違っているようです。これは、データベースの制限が、明らかにデータベースに関連していないコードの部分にまで広がっていることを意味します。

もちろん、これはすべて、静かに切り捨てを続けたいという前提に基づいています。切り捨てが発生した場合にユーザー フィードバックを提供したい場合は、そのフィードバックを実行する適切なポイントがどこにあるかを判断する必要があります。

于 2012-12-17T17:03:12.910 に答える
3

Delphi 7 から XE3 に移植するだけの場合は、そのままにしておいてください。また、「ShortString」は廃止される可能性がありますが、完全に削除された場合は帽子をかぶるでしょう。それなしでは再構築できないコードがたくさんあるからです。ShortString + Records は、バイト指向のファイル オブ レコード データ ストレージを指定する唯一の実用的な方法です。Delphi は、ShortString を削除したり、その動作を変更したりすることは決してありません。既存の Delphi コードに壊滅的な影響を与える可能性があります。したがって、本当にレコードを定義してその長さを制限する必要があり、それらのレコードで Unicode をサポートしたくない場合は、ShortString コードの使用や記述をやめる理由はありません。そうは言っても、私は短い文字列と File-of-record を嫌います。それらがなくなることを望み、非推奨とマークされてうれしいです。

そうは言っても、私はメイソンとデビッドに完全に同意します。長さのチェックと検証はプレゼンテーション/検証の問題であり、Delphi の強力な型付けは適切な場所でも適切な方法でもありません。クラスに検証制約を設定する必要がある場合は、constraint-storage を実装するヘルパー クラスを記述します (EmployeeName は文字列フィールドであり、EmployeeName には以下の長さ制限があります)。たとえば、編集コントロールでは、これは既にプロパティです。コード内で静的に制約を表現しようとするよりも、新しいバインディング システムを使用して DB フィールドをビジュアル フィールドにマッピングする方がはるかに好ましいと思われます。

ユーザー入力の検証とストレージは異なり、長さ制限はデータ構造ではなく GUI コントロールで設定する必要があります。

たとえば、Unicode の幅はあるが長さが制限された文字列が必要な場合は、UnicodeChar の配列を使用できます。Delphi の新しいクラス ヘルパー メソッドを使用して、独自の LimitedString クラスを作成することもできます。しかし、そのようなアプローチは保守可能で安定した設計ではありません。

SQL データベースにVARCHAR(100)type で宣言されたフィールドがあり、ユーザーの入力を 100 文字に制限したい場合は、GUI レイヤーでそれを行い、舞台裏で静かに切り捨て (実際にはデータの破損) を強制することを忘れてください。

于 2012-12-17T23:12:16.657 に答える
3

私の理解では、私の答えは「レイヤーを混ぜないでください」でなければなりません。

文字列の長さは、データベース レイヤー レベル (列幅) またはビジネス アプリケーション レイヤー (カード番号の検証など) で指定されているのではないかと思います。

「純粋な Delphi コード」の観点からはstring、永続化レイヤーまたはビジネス レイヤーに到達しない限り、変数に最大長があることを認識すべきではありません。

属性を使用することはアイデアかもしれません。ただし、レイヤーを混合しているのとまったく同じ理由で、ソースコードを「汚染」する可能性があります。

したがって、私が推奨するのは、データの期待値を指定する専用のデータ モデリングを使用することです。次に、Delphivarレベルでは、単純な を定義するだけですstring。これは、mORMotフレームワークがデータのフィルタリングと検証を実装する方法とまったく同じです。モデル レベルで、いくつかの専用クラスを使用して、便利で拡張可能でクリーンです。

于 2012-12-17T19:43:46.120 に答える
1

あなたはデルファイのバージョンを指定していません.デルファイ2010で私のために働くものは次のとおりです:

バージョン 1 :

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;

バージョン 2 :

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;

// データを db にプッシュする前に .EnsureLength を呼び出す必要があります...

個人的には、レコードをオブジェクトに置き換えることをお勧めします。そうすれば、さらに多くのトリックを実行できます。

于 2012-12-18T03:02:50.310 に答える
1

私はこの問題を抱えていました.Delphi 6から2009へのアップグレードは、古いASCII文字列を個々のASCII文字として扱うことが不可欠でした.

このプログラムは ASCII ファイル (NO ANSI でもあります) を出力し、最後の数字をオーバーパンチして負を示すなどの概念を持っています。したがって、ファイル形式は少し前に戻ります。

2009 年の最初のビルドの後 (10 年前のコードですよね!) ユニット名などを並べ替えた後、文字通り何百ものエラー/不正な割り当てとデータ損失/変換の警告が報告されました...

文字列と文字を使用した Delphi のバックルーム操作/魔法がどれほど優れていても、私はそれを十分に信頼していませんでした。最後に、すべてが元の状態に戻ったことを確認するために、それらすべてをバイト配列として再宣言し、それに応じてコードを変更しました。

于 2012-12-17T20:20:05.503 に答える