1

在查询 MS Access 时,我了解到(如何抢占“指定强制转换无效”异常?)我必须通过防御性查询 Text(字符串)值可能为空(或者,显然实际上是 null)使用“ IIF(ISNULL(colName),'',colName) ”构造,例如:

SELECT id, pack_size, IIF(ISNULL(description),'',description), department, subdepartment, IIF(ISNULL(vendor_id),'',vendor_id), IIF(ISNULL(vendor_item),'',vendor_item), avg_cost, list_cost FROM PhunkyPlatypi ORDER BY id

我假设这仅对指定为 required == false 的 Text 列是必需的。我的 ASSumption 错了吗 - 我必须对所有非必需的列执行此操作吗?

具体来说,如果我需要对数据类型为 double 的列进行防御性查询,是否可以这样做:

IIF(ISNULL(two_bagger),0.0,two_bagger)

?

或者更好(人们总是希望):是否有一些更干净/不那么突兀的方式来处理不包含每列数据的结果集?

如果它有任何区别,我正在使用 OleDbDataReader 从 .NET 4.5.1 Web API 应用程序查询 MS Access 数据库(新酒皮中的旧抱怨?)

更新

回复:HansUp 的(Reach for the Sky?)建议:“也许从 .Net 方面进行攻击并让代码更适合 Nulls 会更有成效”,这样的方法是否可以做到,或者是有一种更有效/更安全的方法:

if (null == oleDbD8aReader.GetString(2))
{
    description = "Blank description";
}
else
{
    description = oleDbD8aReader.GetString(2);
}

?

更新 2

我更改了代码以检查 DBNull,当它是 DBNull 时,将值设置为基于数据类型的通用值(text 为 string.empty,int 为 0,double 为 0.00),但我仍然得到相同的错误消息。

更新 3

我在这一行收到“指定的演员表无效”:

long RedemItemId = (oleDbD8aReader["dbp_id"] is DBNull ? 0 : (long)oleDbD8aReader["dbp_id"]);

dbp_id 是 Access 表中的 LongInt

从查询返回的数据在该列中包含以下值:

5
20
30
40
45
60
70
75
90
120
120

...那么这些值中的任何一个怎么可能无法长时间转换?我应该使用“Convert.ToX()”而不是“(long)”吗?或者...???

4

3 回答 3

2

(回应关于在客户端处理事情的附加问题......)

OleDbDataReader将返回一个 Access 数据库Text字段System.String(如果它包含一个值),或者System.DBNull(如果它Null在数据库中)。

因此,如果要将DBNull值转换为空(零长度)字符串,只需使用

cmd.CommandText =
    "SELECT txtCol FROM Clients WHERE ID = 3";
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string result = rdr["txtCol"].toString();

在您确实关心返回的值是否经过DBNull测试的情况下

cmd.CommandText =
    "SELECT txtCol FROM Clients WHERE ID = 3";
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
string result;
if (rdr["txtCol"] is DBNull)
{
    result = "{That field was Null.}";
}
else
{
    result = rdr["txtCol"].ToString();
}

(请注意,在 C# 中,null它们DBNull不同的生物。)

编辑

同样,对于数字数据库字段(例如,类型Double),您可以使用“强制”空值为零

cmd.CommandText =
    "SELECT dblCol FROM Clients WHERE ID = 3";
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
double dResult = (rdr["dblCol"] is DBNull ? 0 : Convert.ToDouble(rdr["dblCol"]));
于 2013-10-25T19:35:52.003 回答
2

“对于已指定为必需的文本列 == false ...我是否必须对所有非必需列执行此操作?”

也许。如果您没有为它们设置Required = True,则具有其他数据类型(数字、日期/时间等)的列可能包含 Null。此外,即使源表中的所有列都需要 = True ,使用LEFTor也可以在不匹配的行中获得 Null。RIGHT JOIN如果您不希望查询输出中有任何 Null,则必须对所有可能的情况进行替换。

“关于双数据类型的列,这是这样做的方法吗”

IIF(ISNULL(two_bagger),0.0,two_bagger)

是的,这应该有效。或者,如果您愿意,也可以这样做...

IIF(two_bagger Is Null,0.0,two_bagger)

从 OleDb 来看,我不相信有“一些更干净/不那么突兀的方式来处理每列中不包含数据的结果集”。也许从.Net侧面攻击它并让代码更适应 Nulls 会更有效率……然后你就不需要要求 db 引擎用其他东西代替 Nulls。

于 2013-10-25T16:16:22.257 回答
0

有一个非 SQL 非 Jet 但 Access 函数 NZ 可以提供帮助

IIF(ISNULL(description),'',description)

几乎等于

nz(description,'')

通过 oleDbReader 检查它是否可用

于 2013-10-25T17:51:30.513 回答