1

システム間キャッシュを使用するのは初めてで、キャッシュに保存されているデータをクエリしているときに、基になるシステムのデータを正確に表していないように見えるクラスによって公開されるという問題に直面しています。グローバルに格納されるデータは、ほとんどの場合、オブジェクトコードで定義されているものよりも大きくなります。

そのため、以下のようなエラーが頻繁に発生します。

Msg 7347, Level 16, State 1, Line 2
OLE DB provider 'MSDASQL' for linked server 'cache' returned data that does not match expected data length for column '[cache]..[namespace].[tablename].columname'. The (maximum) expected data length is 5, while the returned data length is 6.

グローバルに保持されているデータを収容できるようにオブジェクト定義(SQLマッピング)が維持されるようにするために、ある種の品質プロセスを実装した経験はありますか?

Property columname As %String(MAXLEN = 5, TRUNCATE = 1) [ Required, SqlColumnNumber = 2, SqlFieldName = columname ];

この特定の例では、システムには最大lenが5で定義された列がありますが、システムに格納されているデータの長さは6文字です。

このような状況を積極的に監視して修復するにはどうすればよいですか。

/ *

これらのオブジェクト定義をキャッシュに作成しませんでした

* /

4

3 に答える 3

3

「監視と修復」があなたにとって何を意味するのかは完全には明らかではありませんが、次のようになります。

データベース側をどの程度制御できますか?キャッシュは、データ型クラスのLogicalToODBCメソッドを使用してグローバルからODBCに変換するときに、データ型のコードを実行します。プロパティタイプを%Stringから独自のクラスAppropriatelyNamedStringに変更すると、そのメソッドをオーバーライドして自動的に切り捨てることができます。それがあなたがしたいことなら。%Library.CompiledClassクラスを使用して、プログラムですべての%Stringプロパティタイプを変更することができます。

キャッシュ内でコードを実行して、(ある程度理論上の)最大長を超えるプロパティを持つレコードを見つけることもできます。これには明らかに全表スキャンが必要です。そのコードをストアドプロシージャとして公開することも可能です。

繰り返しますが、あなたが何をしようとしているのか正確にはわかりませんが、それらはいくつかの選択肢です。彼らはおそらくあなたが望むよりもキャッシュ側に深く入る必要があります。

そもそも悪いデータを防ぐ限り、一般的な答えはありません。キャッシュを使用すると、プログラマーはオブジェクトやテーブルの定義をバイパスして、グローバルに直接書き込むことができます。その場合は、コードを直接修正する必要があります。

編集:これは不良データの検出に役立つ可能性のあるコードです。あなたが面白いことをしているならそれはうまくいかないかもしれませんが、それは私にとってはうまくいきました。メソッドやタグに分割したくなかったので、ちょっと醜いです。これはコマンドプロンプトから実行するためのものであるため、おそらく目的に合わせて変更する必要があります。

{
    S ClassQuery=##CLASS(%ResultSet).%New("%Dictionary.ClassDefinition:SubclassOf")
    I 'ClassQuery.Execute("%Library.Persistent")  b  q
    While ClassQuery.Next(.sc) {
    If $$$ISERR(sc) b  Quit
        S ClassName=ClassQuery.Data("Name")
        I $E(ClassName)="%"   continue
        S OneClassQuery=##CLASS(%ResultSet).%New(ClassName_":Extent")
        I '$IsObject(OneClassQuery) continue  //may not exist
        try {
        I 'OneClassQuery.Execute()  D OneClassQuery.Close() continue
        }
        catch
        {

            D OneClassQuery.Close()
            continue
        }
        S PropertyQuery=##CLASS(%ResultSet).%New("%Dictionary.PropertyDefinition:Summary")
        K Properties
        s sc=PropertyQuery.Execute(ClassName)  I 'sc D PropertyQuery.Close()  continue
        While PropertyQuery.Next()
        {
            s PropertyName=$G(PropertyQuery.Data("Name"))
            S PropertyDefinition=""
            S PropertyDefinition=##CLASS(%Dictionary.PropertyDefinition).%OpenId(ClassName_"||"_PropertyName)
            I '$IsObject(PropertyDefinition)  continue
            I PropertyDefinition.Private  continue
            I PropertyDefinition.SqlFieldName=""    
            {
                S Properties(PropertyName)=PropertyName
            }
            else
            {
                I PropertyName'="" S Properties(PropertyDefinition.SqlFieldName)=PropertyName
            }
        }
        D PropertyQuery.Close()

        I '$D(Properties) continue

        While OneClassQuery.Next(.sc2)  {
            B:'sc2
            S ID=OneClassQuery.Data("ID")
            Set OneRowQuery=##class(%ResultSet).%New("%DynamicQuery:SQL")
            S sc=OneRowQuery.Prepare("Select * FROM "_ClassName_" WHERE ID=?") continue:'sc
            S sc=OneRowQuery.Execute(ID) continue:'sc
            I 'OneRowQuery.Next() D OneRowQuery.Close() continue
            S PropertyName=""
            F  S PropertyName=$O(Properties(PropertyName))  Q:PropertyName=""  d
            . S PropertyValue=$G(OneRowQuery.Data(PropertyName))
            . I PropertyValue'="" D
            .. S PropertyIsValid=$ZOBJClassMETHOD(ClassName,Properties(PropertyName)_"IsValid",PropertyValue)
            .. I 'PropertyIsValid W !,ClassName,":",ID,":",PropertyName," has invalid value of "_PropertyValue
            .. //I PropertyIsValid W !,ClassName,":",ID,":",PropertyName," has VALID value of "_PropertyValue
            D OneRowQuery.Close()
        }
        D OneClassQuery.Close()
    }   
    D ClassQuery.Close()
}
于 2012-01-16T18:49:48.670 に答える
0

最も簡単な解決策は、MAXLENパラメーターを6以上に増やすことです。Caféは、保存時にMAXLENとTRUNCATEのみを適用します。他のCachéコード内では、これは通常は問題ありませんが、残念ながら、ODBCクライアントはこれがより厳密に適用されることを期待する傾向があります。もう1つのオプションは、SELECT LEFT(columnname、5)...のようにSQLを作成することです。

于 2011-12-20T01:55:46.990 に答える
0

たとえば、すべてのIntegration Servicesパッケージに使用する最も簡単なソリューションは、すべてのnvarcharまたはcharデータを正しい長さにキャストするクエリを作成することです。このようにして、私のデータが切り捨てのために失敗することはありません。オプション:最初に次のようなクエリを実行します:SELECT Max(datalength(mycolumnName))from cachenamespace.tablename.mycolumnName

新しいクエリ:SELECT cast(mycolumnname as varchar(6))as mycolumnname、convert(varchar(8000)、memo_field)AS memo_field from cachenamespace.tablename.mycolumnName

データを取得する際の苦痛は軽減されますが、解消されるわけではありません。いずれかのタイプのoledbプロバイダーを使用する場合、またはSQL ServerでOPENQUERYを使用する場合、キャストは、内部OPENQUERYからデータを取得する外部クエリではなく、IntersystemsCACHEdbに送信されるクエリで発生する必要があります。

于 2017-09-21T15:03:13.570 に答える