SQL:指定的强制转换无效

时间:2012-06-08 19:31:01

标签: c# sql

注意:我正在寻找为什么会发生这种情况以及如何解决它,我不是在寻找解决方法。这似乎是服务器(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是打破的地方 - &gt; 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"] - &gt; “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,我想知道为什么必须这样做。我不妨把所有类型作为字符串放在表中。在这一点上,我不是在寻找一种解决方法,我想要理解为什么它不能像它那样工作。

9 个答案:

答案 0 :(得分:9)

您列出的两个表都显示int作为数据类型,但听起来好像是两个不同数据库中同一个表的两个版本。

我相信OTHER JOIN的那个表在一个数据库中具有不同的数据类型。

两个数据库中File_fileType.Id的数据类型是什么?

您的JOIN

join file_filetype on file_importtable.FileTypeID = file_filetype.ID

导致隐式转换。

enter image description here

上图显示了SQL Server如何允许或执行数据类型转换。

您能否在上面的JOIN

中显示两个版本的两个版本的DDL

答案 1 :(得分:6)

对我而言,听起来有些古怪的配置设置很难找到。有一个名为Redgate SQL Compare的工具在检测数据库模式之间的差异时执行惊人的工作。

他们进行了为期14天的试验。我会尝试下载并运行数据库之间的比较。

答案 2 :(得分:3)

执行SQL排序规则的匹配吗?如果您在数据库之间遇到不同的行为,这可能是您的问题。右键单击每个数据库并选择属性,排序规则应指定为* Latin1_General_CI_AS *如果它们不同则肯定要排除。

答案 3 :(得分:1)

你必须从字符串中转换。

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

编辑:如果你想要一个适用于BOTH sql server 2008和2000的解决方法

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

答案 4 :(得分:1)

Visual Studio(版本Premium和Ultimate根据this)附带了一个数据库比较工具 - 您选择两个数据库,它会显示差异并为您提供一组脚本,将一个脚本移动到其他状态。从那里开始,尝试嗅出不同的配置(因为我希望这是一个配置问题)。在Visual Studio中查看Data \ Schema Compare和Data \ Data Compare。

答案 5 :(得分:1)

已经确认存在至少一个错误。由于我没有整个图像,因此很难准确。因此,我建议进行两次检查。

第一次检查应该在两个数据库上使用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(SQL 2008)上阅读有关INFORMATION_SCHEMA.COLUMNS的更多信息。来自不同来源的相同信息。

样品:

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服务器。

答案 6 :(得分:1)

在我决定删除表格并使用

重新创建的方案中

[script table as] - &gt; [创建]

从给我问题的同一个表中,然后重新插入所有相同的数据。这解决了这个问题。所以我不相信表的DML发生了变化,数据也没有改变,但这就解决了我的问题。

答案 7 :(得分: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()

答案 8 :(得分:0)

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