15

注:これが発生する理由と修正方法を探していますが、回避策は探していません。これはサーバー(SQL Serverまたは接続文字列)の問題のようです。

sql 2008データベース(データベースA)に接続されているプログラムがあり、intと文字列が返されて実行されるインラインsqlがあり、正常に動作します。しかし、別の2008データベース(データベースB)に切り替えるように求められましたが、すべてが文字列として返され、指定されたキャストがC#から無効になっています。SQL2008(データベースA)に接続すると、これは言いません。これはインラインSQLステートメントであるため、SQLステートメントは変更されず、データベースのテーブルスキーマは同じです。これをint主キーで実行するアイデアはありますか?

もともとは2000年から2008年の問題だと思っていましたが、2008年も問題があります。両方のデータベースはSQLサーバーの同じインスタンス上にあり、これらは接続文字列です

接続文字列

  Server=Server01\instance;Database=Fraud_Micah; Trusted_Connection=yes <- Server 2008 (this one does not)
  Server=Server02\instance;Database=Fraud; Trusted_Connection=yes <- Server 2008 (this one works)

両方のデータベースのDB互換性レベルは100です

selectステートメント

select *, delimeter, file_filetype.LocalPath, ArchiveDir, EmailList
from file_importtable 
join file_filetype on file_importtable.FileTypeID = file_filetype.ID
where importsuccessdate is null and transferdate is not null
and remotediscoverdate is not null 
and OriginalFileName in ('Test987.xml.pgp')

fileTypeIDその破壊->InvalidCastException: Specified cast is not valid.

C#コード(リーダーはSQLDataReaderタイプであることに注意してください)

if (!(reader.IsDBNull(reader.GetOrdinal("FileTypeID"))))
{
    file.FileTypeID = reader.GetInt32(reader.GetOrdinal("FileTypeID"));
}

列の定義は次[FileTypeID] [int] NULLのとおりです。、テーブルにnull値はありません。

C#コードはこれから来ているとは思いません、それはintですか?public int? FileTypeID { get; set; }

デバッグモードの場合:reader["FileTypeID"]-> "1"実際には文字列ですが、2008データベースに接続すると、 "1"の1が返されるのはなぜですか?

2008テーブルA定義

[ProcessSuccessDate] [datetime] NULL,
[ProcessSuccessUser] [datetime] NULL,
[FileTypeID] [int] NULL,
[HoldDate] [datetime] NULL,

2008年表B定義

ProcessSuccessDate] [datetime] NULL,
[ProcessSuccessUser] [datetime] NULL,
[FileTypeID] [int] NULL,
[HoldDate] [datetime] NULL,

file.FileTypeID = (int)reader["FileTypeID"];同じ結果が得られます。

を行う

     file.FileTypeID (int)reader.GetInt32(reader.GetOrdinal("FileTypeID"));

動作しますが、intとしてすでに戻ってくるはずのすべての列に対してこれを実行したくありません。このようなSQLも記述します。

     select Convert(int, FileTypeID) as FileTypeId, delimeter, file_filetype.LocalPath, ArchiveDir, EmailList

問題を回避することもできますが、テーブルで型をintとして設定しているのに、なぜこれを行う必要があるのか​​を知りたいです。すべてのタイプを文字列としてテーブルに配置したほうがよいでしょう。この時点では、回避策を探していません。なぜそれが本来のように機能しないのかを理解したいと思います。

4

9 に答える 9

10

リストする両方のテーブルintはデータ型として表示されますが、これらは2つの異なるデータベースにある同じテーブルの2つのバージョンのようです。

OTHERテーブル、つまりあなたが使用するテーブルは、1JOINつのデータベースで異なるデータ型を持っていると思います。

File_fileType.Id両方のDBのデータ型は何ですか?

あなたのJOIN

join file_filetype on file_importtable.FileTypeID = file_filetype.ID

暗黙の変換を引き起こしています。

ここに画像の説明を入力してください

上のグラフは、SQLServerがデータ型の変換を許可または実行する方法を示しています。

上記の両方のテーブルの両方のバージョンのDDLを表示できますJOINか?

于 2012-06-12T13:28:51.527 に答える
6

私には、見つけるのが難しいいくつかの風変わりな構成設定があるように思えます。Redgate SQL Compareと呼ばれるツールがあり、データベーススキーマ間の違いを検出するのに驚くべき仕事をします。

彼らは14日間の試用版を持っています。ダウンロードして、データベース間の比較を実行してみます。

于 2012-06-11T19:35:11.683 に答える
3

SQL照合は一致しますか?データベース間で異なる動作が発生している場合は、これが問題である可能性があります。各データベースを右クリックしてプロパティを選択します。照合は*Latin1_General_CI_AS*のように指定する必要があります。それらが異なる場合は、間違いなく除外する必要があります。

于 2012-06-11T15:38:50.050 に答える
1

私がテーブルを削除し、それを使用して再作成することを決めたもののスキームで

[スクリプトテーブルとして]->[作成]

問題を引き起こしていた同じテーブルから、すべて同じデータを再挿入しました。これで問題は解決しました。したがって、テーブルのDMLが変更され、データも変更されなかったとは思いませんが、これが私の問題を解決したものです。

于 2012-06-13T20:21:12.173 に答える
1

文字列からキャストする必要があります。

file.FileTypeID = int.Parse((string)reader["FileTypeID"]);

編集:SQLServer2008と2000の両方で機能する回避策が必要な場合

file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]);
于 2012-06-08T20:29:29.483 に答える
1

Visual Studio(これによるとエディションPremiumとUltimate )にはデータベース比較ツールが付属しています-2つのデータベースを選択すると、差分が表示され、一方を他方の状態に移動する一連のスクリプトが提供されます。そこから始めて、異なる構成をスニッフィングしてみてください(これは構成の問題であると予想されるため)。VisualStudioでData\SchemaCompareとData\DataCompareを確認してください。

于 2012-06-11T19:39:33.547 に答える
1

少なくとも1つのバグの存在はすでに認められています。私は全体像を持っていないので、正確にするのは難しいです。したがって、2つのチェックをお勧めします。

最初のチェックは、INFORMATION_SCHEMA.COLUMNS(必要なレベルには十分すぎる)を使用して両方のデータベースで行い、スキーマが同一であることを確認する必要があります。INFORMATION_SCHEMA.COLUMNSの詳細については、 http://msdn.microsoft.com/en-us/library/aa933218(v = sql.80).aspx (SQL 2000)またはhttp://msdn.microsoft.com/を参照してください。 en-us / library / ms188348(SQL2008)。異なるソースからの同じ情報。

サンプル:

SELECT * FROM INFORMATION_SCHEMA.COLUMNS;

スキーマが同一である場合は、提示した部分に表示されていないコードのバグがある可能性があります。完全なコードですべてが正しいことを確認するには、次のようにselectステートメントを変更して簡単なチェックを行います。

select CAST(fileTypeID as int), ..., file_filetype.LocalPath, ArchiveDir, EmailList
from file_importtable 
join file_filetype on file_importtable.FileTypeID = file_filetype.ID
where importsuccessdate is null and transferdate is not null
and remotediscoverdate is not null 
and OriginalFileName in ('Test987.xml.pgp')

失敗した場合は、ブレークポイントとF11を使用して、デバッグモードで段階的にテストを実行します。(時々、ルーツに戻ると、目の前に見えないものを確認するのに役立つ場合があります-この場合はほとんどありません)。

上記に従うことにより、(うまくいけば)原因を見つけることができます。

最後のヒント(他のことをする前の最初のステップかもしれません):SQLサーバーに最新のサービスパックが適用されていることを確認してください。

于 2012-06-12T13:12:26.680 に答える
0

あなたがこれを解決していないので、おそらくGetSqlInt32代わりに方法を試してください。

file.FileTypeID = reader.GetSqlInt32((fieldTypeIDOrdinal).ToNullableInt32();

IsDBNullと組み合わせSqlInt32ToNullableInt32これに対処するので、私はチェックを含めていないことに注意してください。

ToNullableInt32拡張メソッドはどこにありますか。

public static int? ToNullableInt32(this SqlInt32 value)
{
    return value.IsNull ? (int?) null : value.Value;
}

reader.GetOrdinal("FileTypeID")補足として、これはパフォーマンス優先アプリであるとおっしゃいました。この場合、ループごとにこれを行うのではなく、順序値を事前に計算することをお勧めします。reader.Read()

于 2012-06-09T05:32:43.837 に答える
0

file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]); それ以外の file.FileTypeID = (int)reader["FileTypeID"];

于 2012-06-11T15:00:10.777 に答える