2010-11-24 9 views
1

FoxProデータベースからFoxPro OLE DBドライバを使用してSQL Serverデータベースに一部のデータをインポートしています。私が取っているアプローチは、FoxProテーブルをループし、すべてのレコードをDataTableに選択し、SqlBulkCopyを使用してそのテーブルをSql Serverに挿入する方法です。私はそれがで表示され、問題がFoxProテーブルが数値のために一定の幅を持っていることである行にこれを調査し、ログインしたFoxPro OLEDBドライバを使用してデータをインポート中にエラーが発生しました

System.InvalidOperationException: The provider could not determine the Decimal value. For example, the row was just created, the default for the Decimal column was not available, and the consumer had not yet set a new Decimal value. 

:これは私が次のエラーを取得する少数の例を除いて正常に動作します。 1は1.00として格納されますが、10は10.0として格納され、問題を引き起こしている小数点の後の1桁です。私はそれを解決するために苦労している問題を今見つけた。次の関数は、私がデータテーブルにOLEDBReaderを変換するために使用していますものです:

private DataTable FPReaderToDataTable(OleDbDataReader dr, string TableName) 
    { 
     DataTable dt = new DataTable(); 

     //get datareader schema 
     DataTable SchemaTable = dr.GetSchemaTable(); 
     List<DataColumn> cols = new List<DataColumn>(); 
     if (SchemaTable != null) 
     { 
      foreach (DataRow drow in SchemaTable.Rows) 
      { 
       string columnName = drow["ColumnName"].ToString(); 
       DataColumn col = new DataColumn(columnName, (Type)(drow["DataType"])); 
       col.Unique = (bool)drow["IsUnique"]; 
       col.AllowDBNull = (bool)drow["AllowDBNull"]; 
       col.AutoIncrement = (bool)drow["IsAutoIncrement"]; 
       cols.Add(col); 
       dt.Columns.Add(col); 
      } 
     } 

     //populate data 
     int RowCount = 1; 
     while (dr.Read()) 
     { 
      DataRow row = dt.NewRow(); 

      for (int i = 0; i < cols.Count; i++) 
      { 
       try 
       { 
        row[((DataColumn)cols[i])] = dr[i]; 
       } 
       catch (Exception ex) { 
        if (i > 0) 
        { 
         LogImportError(TableName, cols[i].ColumnName, RowCount, ex.ToString(), dr[0].ToString()); 
        } 
        else 
        { 
         LogImportError(TableName, cols[i].ColumnName, RowCount, ex.ToString(), ""); 
        } 
       } 
      } 
      RowCount++; 
      dt.Rows.Add(row); 
     } 
     return dt; 
    } 

私は何をしたいのは、小数第1位の問題を持っている値をチェックしているが、私はでDataReaderオブジェクトから読み取ることができませんこれらのすべての場合に。 、

The provider could not determine the String value. For example, the row was just created, the default for the String column was not available, and the consumer had not yet set a new String value. 

私は列がこれを許可しないようFoxProデータを更新することができません:私は、次のようなエラーが返されますが、この後、私は問題の行にdr.GetString(i)を使用していることができると思っているだろうDataReaderからレコードを読み取って修正するにはどうすればよいですか?キャスト/ dr.GetValue/dr.GetDataのすべての組み合わせを試してみましたが、すべて同じエラーのバリエーションがあります。

次のようにFoxProテーブルの構造は次のとおりです。

Number of data records:  1664  
Date of last update:   11/15/10 
Code Page:     1252  
       Field  Field Name               Type                         Width       Dec     Index Collate           Nulls        Next        Step 
        1  AV_KEY                Numeric                         6             Asc Machine            No 
        2  AV_TEAM                Numeric                         6                            No 
        3  AV_DATE                Date                          8                            No 
        4  AV_CYCLE                Numeric                         2                            No 
        5  AV_DAY                Numeric                         1                            No 
        6  AV_START                Character                         8                            No 
        7  AV_END                Character                         8                            No 
        8  AV_SERVICE               Numeric                         6                            No 
        9  AV_SYS                Character                         1                            No 
        10  AV_LENGTH                Numeric                         4        2                     No 
        11  AV_CWEEKS                Numeric                         2                            No 
        12  AV_CSTART                Date                          8                            No 
** Total **                                                 61 

それは私があなたがVisual FoxProを取得へのアクセス権を持っている場合は知らないが、それが持っている問題

答えて

0

を引き起こしているav_length列でありますSQL Serverに直接アップロードできるアップサイジングの「ウィザード」。

それが適切に解釈取得されていませんメモ/ BLOB型のカラムを持つ問題になる可能性がありDownload Visual Foxpro 9, SP2

経由でMSの裁判のための無料ダウンロードのように見えます。

+0

FoxProがインストールされていて、データを表示できます。問題は固定幅の数値フィールドで表示されます。 Foxproでは、フィールドは幅が4であると定義されているので、0〜9の数字は小数点以下2桁(0.00、1.00など)で表示されます。 9以上の数字は1で表示されます。 10.0,11.0であり、問​​題を引き起こしているのはこれらのフィールドです。私はそれを修正するためにdatareaderから値を取得することはできません。この全体のインポートプロセスは、FPデータベース – Macros

+0

@Macrosを変更することなく、.netプログラム内で発生することが重要です。 VFPでテーブルを使用し、LIST STRUCTURE TO Sample.TXTを実行して、ここでその構造をコピー/ペーストし、問題のあるカラム定義を表示できますか?あなたが遭遇している出力に対して、4の幅が非常に奇妙に聞こえます。 – DRapp

+0

私は質問を更新しました。問題を引き起こしているのはav_lengthの列です。 – Macros

0

あなたは、あなたがそれをしようとしてきたか...あなたは明示的に列のデータ型をテストし、それを強制する場合があります

row[((DataColumn)cols[i])] = dr[i]; 

を持っているあなたのtry/catchではわからタイプキャストを言及はなく、 ...何か以下(DataType.ToStringのオブジェクト参照(の正のではない)のような、しかし、あなたはあなたのランニング/デバッグ中にあることを見つける必要があります。

if(cols[i].DataType.ToString().ToLower().Contains("int")) 
    row[((DataColumn)cols[i])] = (int)dr[i]; 
else 
    row[((DataColumn)cols[i])] = dr[i]; 

あなたは明らかにあまりにも他の種類のテストがあります。 ..

+0

私はこのようにキャストしようとしましたが、datareadersメソッドを使用しています。 dr.GetString、dr.GetValueとなし! – Macros

0

あなたのリストの構造から、それは何をしているのですか。リストされたテーブル構造のVFPでは、AV_LENGTHはnumeric型であり、長さは4で、2は小数点以下の位置に割り当てられます。したがって、MOSTの値は「9.99」になります。 VFPは、数値フィールドの入力を小数点以下2桁まで強制します。小数点以下は1、残りは整数部になります。

残りの数値ベースのフィールドは長さ付きの数値型ですが、小数点以下の桁数がすべてであることを示す小数点以下の桁数はありません。したがって、整数データ型として修飾されます。小数点付きの数値は、浮動小数点型または二重列型にする必要があります。

言われているように、私は10進数の4の2進数で10.0の値を取得する方法についても分かりません。これは、実際にはこのようにフィールドに保存される構造体の割り当てられた意図よりも大きな数値を強制的に強制していた最初の時間です。

+0

それは私に悩まされていることです - 私はFoxProがそれを許可する理由を見ることができませんし、データレディヤーの列を読み取ることができないという事実を受け入れる場合でも – Macros

+0

@Macros、ここで示されているように、定義のために強制的に大きすぎる値があなたのデータリーダーを混乱させるためかもしれません。私はav_lengthのselect max()を実行して最大値が何であるかを確認してから、最大の正当な値を考慮して構造を変更し、その値から変更します。どんな数字になるのだろうか。 – DRapp

+0

この特定のインスタンスの最大値は10.0です。これはわずか2行です。私が持っている問題は、インポートはエンドユーザーが実行する必要がある移行プロセスの一部なので、たとえこのデータベースインスタンスを変更しても、潜在的に同じ問題を抱える何百人ものユーザーがいることです。 – Macros

0

FoxProにこの問題がある理由を思い出しません。私は数字がどのように格納されるかと関係があると思います。それにかかわらず、解決策は、(A)データをクリーンアップするか、(B)フィールドのサイズを変更してより大きな値を可能にすることです。以下のサンプルコードは、この問題を示しています。

 
* create a table that can store a value between -0.99 and 99.99 
CREATE TABLE "TEST.DBF" (av_length N(4,2)) 

* insert values between 1.10 and 22,222.22222 
INSERT INTO "TEST" (av_length) VALUES(1.1) 
INSERT INTO "TEST" (av_length) VALUES(2.2) 
INSERT INTO "TEST" (av_length) VALUES(11.11) 
INSERT INTO "TEST" (av_length) VALUES(22.22) 
INSERT INTO "TEST" (av_length) VALUES(111.111) 
INSERT INTO "TEST" (av_length) VALUES(222.222) 
INSERT INTO "TEST" (av_length) VALUES(1111.1111) 
INSERT INTO "TEST" (av_length) VALUES(2222.2222) 
INSERT INTO "TEST" (av_length) VALUES(11111.11111) 
INSERT INTO "TEST" (av_length) VALUES(22222.22222) 

* view the contents of the table 
* note that records 3 to 10 do not match the field definition 
BROWSE NORMAL 

IF MESSAGEBOX("Fix the Data? Select to Change the Field Definition", 0+4+32) = 6 
    * Solution A: fix the data, and view the table contents again 
    REPLACE ALL av_length WITH MIN(av_length, 9.99) IN "TEST" 
    BROWSE NORMAL 
ELSE 
    * Solution B: change the field definition, and view the table contents again 
    * note that records 9 & 10 still need to be fixed 
    ALTER TABLE "TEST.DBF" ALTER COLUMN av_length N(12,6) 
    BROWSE NORMAL 
ENDIF 
+0

最小値にすることは、おそらく日付を任意に修正するための良い選択ではない、あなたのalter tableが良い選択です。しかし、コードを実行しても、実際にはレコード8までの値が保存されています。 FoxproとVFPの25年以上の後、私はこのことを可能な限り思い出しませんでしたが、入力マスクコントロールを使ってフィールドの容量をオーバーフィルしようとしたことはありませんでした。 – DRapp

関連する問題