繁体   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