簡體   English   中英

SQL:指定的強制轉換無效

[英]SQL: Specified cast is not valid

注意:我正在尋找為什么會發生這種情況以及如何解決它,我不是在尋找解決方法。 這似乎是服務器(SQL Server或連接字符串)問題。

我有一個程序連接到一個sql 2008數據庫(數據庫A),我有內聯sql運行,其中有int和字符串返回,它工作正常。 但我被要求切換到另一個2008數據庫(數據庫B),現在一切都以字符串形式返回,我從C#獲取指定的強制轉換,當我連接到sql 2008(數據庫A)時不說這個。 這是一個內聯sql語句,因此sql語句不會更改,並且數據庫的表模式是相同的。 它在int主鍵上執行此操作任何人都有任何想法?

我原本以為這是2000年至2008年的問題,但我現在也有一些問題。 兩個數據庫都在sql server的同一個實例上,這些是連接字符串

連接字符串

  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 compatibility_level均為100

選擇聲明

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 ,表中沒有空值。

我不認為C#代碼來自於它,它是一個int? public int? FileTypeID { get; set; }

在調試模式下: reader["FileTypeID"] - >“1”它實際上是一個字符串,但為什么當我連接到2008數據庫時它會返回1個“1”的實例

2008表A Def

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

2008年表B Def

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,我想知道為什么我必須這樣做。 我不妨把所有類型作為字符串放在表中。 在這一點上,我不是在尋找一種解決方法,我想要理解為什么它不應該像它一樣工作。

您列出的兩個表都顯示int作為數據類型,但聽起來這些是兩個不同數據庫中同一個表的兩個版本。

我相信OTHER表,你JOIN表,在一個數據庫中有不同的數據類型。

兩個DB中File_fileType.Id的數據類型是什么?

你的JOIN

join file_filetype on file_importtable.FileTypeID = file_filetype.ID

導致隱式轉換。

在此輸入圖像描述

上圖顯示了SQL Server如何允許或執行數據類型轉換。

你能在上面的JOIN顯示兩個版本的兩個版本的DDL嗎?

對我而言,聽起來有一些古怪的配置設置很難找到。 有一個名為Redgate SQL Compare的工具在檢測數據庫模式之間的差異方面做得非常出色。

他們進行了為期14天的試驗。 我會嘗試下載它並在您的數據庫之間進行比較。

SQL排序規則是否匹配? 如果您在數據庫之間遇到不同的行為,這可能是您的問題。 右鍵單擊每個數據庫並選擇屬性,排序規則應指定為* Latin1_General_CI_AS *如果它們不同則肯定要排除。

你必須從字符串中強制轉換。

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

編輯:如果你想要一個適用於BOTH sql server 2008和2000的解決方法

file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]);

Visual Studio(根據版本為Premium和Ultimate)附帶了一個數據庫比較工具 - 您選擇兩個數據庫,它會顯示差異並為您提供一組腳本,將一個腳本移動到另一個狀態。 從那里開始,嘗試嗅出不同的配置(因為我希望這是一個配置問題)。 在Visual Studio中查看Data \\ Schema Compare和Data \\ Data Compare。

已經確認存在至少一個錯誤。 由於我沒有整個圖像,因此很難准確。 因此,我建議兩次檢查。

第一次檢查應該在兩個數據庫上使用INFORMATION_SCHEMA.COLUMNS(對於所需級別來說已經綽綽有余)來驗證模式是否相同。 您可以在http://msdn.microsoft.com/en-us/library/aa933218(v=sql.80).aspx(SQL 2000)或http://msdn.microsoft.com/上閱讀有關INFORMATION_SCHEMA.COLUMNS的更多信息。 en-us / library / ms188348 (SQL 2008)。 來自不同來源的相同信息。

樣品:

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服務器使用最新的服務包進行修補。

在我希望刪除表並使用它重新創建它的方案中

[腳本表為] - > [創建]

從給我問題的同一個表中,然后重新插入所有相同的數據。 這解決了這個問題。 所以我不相信表的DML發生了變化,數據也沒有改變,但這就解決了我的問題。

看來你沒有解決這個問題,也許會嘗試使用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()每個循環reader.Read()

file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]); 而不是 file.FileTypeID = (int)reader["FileTypeID"];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM