[英]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
从检查,结合SqlInt32
与ToNullableInt32
与此对应。
其中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.