15

注意:我正在寻找为什么会发生这种情况以及如何解决它,我不是在寻找解决方法。这似乎是服务器(SQL Server 或连接字符串)问题。

我有一个连接到 sql 2008 数据库(数据库 A)的程序,并且我有运行的内联 sql,它返回了整数和字符串,它工作正常。但是我被要求切换到另一个 2008 数据库(数据库 B),现在所有内容都以字符串形式返回,并且当我连接到 sql 2008(数据库 A)时,我从 C# 得到一个指定的强制转换无效不说这个。这是一个内联 sql 语句,因此 sql 语句没有变化,并且数据库的表模式是相同的。它在 int 主键上执行此操作有人有任何想法吗?

我最初认为这是 2000 年到 2008 年的问题,但我现在在 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)

两个数据库的数据库兼容性级别均为 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 定义

[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为数据类型,但听起来它们是两个不同数据库中同一个表的两个版本。

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

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

你的JOIN

join file_filetype on file_importtable.FileTypeID = file_filetype.ID

导致隐式转换。

在此处输入图像描述

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

你能在上面显示两个表的两个版本的 DDLJOIN吗?

于 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

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

第一次检查应该使用 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 服务器已使用最新的服务包进行修补。

于 2012-06-12T13:12:26.680 回答
1

在事情的计划中,我决定删除表并使用重新创建它

[脚本表] -> [创建]

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

于 2012-06-13T20:21:12.173 回答
1

Visual Studio(根据版本的 Premium 和 Ultimate 版)带有一个数据库比较工具 - 您选择两个数据库,它会向您显示差异并为您提供一组脚本,将一个移动到另一个状态。从那里开始并尝试找出不同的配置(因为我认为这是一个配置问题)。查看 Visual Studio 中的数据\架构比较和数据\数据比较。

于 2012-06-11T19:39:33.547 回答
1

您将不得不从字符串中转换。

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

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

file.FileTypeID = Convert.ToInt32(reader["FileTypeID"]);
于 2012-06-08T20:29:29.483 回答
0

鉴于您尚未解决此问题,请尝试使用该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()

于 2012-06-09T05:32:43.837 回答
0

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

于 2012-06-11T15:00:10.777 回答