【发布时间】:2013-05-27 09:50:00
【问题描述】:
我将 Oracle 的 ODAC.NET 用于针对 Oracle 11 Express 数据库的 .NET 3.5 项目,我看到了我无法解释的行为(而且似乎无法解决)。
ODAC应该是最新的,我3天前刚拉的,版本如下:
- Oracle.DataAccess.dll 版本 2.112.3.0(第 5 版)
- oci.dll(即时客户端)版本 11.2.0.1
我有一个表格 People,它有 3 列:
- 身份证
- 名字
- 姓氏
在代码中,我使用 OracleCommand.ExecuteNonQuery 运行 ALTER TABLE 命令,将名为“MIDDLE_NAME”的新列添加到表中。该命令成功。如果我使用 Oracle SQL Developer 查看表格,就会显示列。一切顺利。
现在,如果我在执行 alter table 后立即使用 OracleCommand.ExecuteReader 和命令文本 SELECT * FROM People 运行,我得到的数据只有 3 列,而不是 4 列!
这里是重现问题的代码:
public void FieldTest()
{
var sql1 = "CREATE TABLE People (" +
"ID NUMBER PRIMARY KEY, " +
"FirstName NVARCHAR2 (200), " +
"LastName NVARCHAR2 (200) NOT NULL)";
var sql2 = "ALTER TABLE People " +
"ADD Middle_Name NUMBER";
var sql3 = "SELECT * FROM People";
var sql4 = "SELECT column_name FROM all_tab_cols WHERE table_name = 'PEOPLE'";
var cnInfo = new OracleConnectionInfo("192.168.10.246", 1521, "XE", "system", "password");
var connectionString = BuildConnectionString(cnInfo);
using (var connection = new OracleConnection(connectionString))
{
connection.Open();
using (var create = new OracleCommand(sql1, connection))
{
create.ExecuteNonQuery();
}
using (var get = new OracleCommand(sql3, connection))
{
using (var reader = get.ExecuteReader())
{
Debug.WriteLine("Columns: " + reader.FieldCount);
// outputs 3, which is right
}
}
using (var alter = new OracleCommand(sql2, connection))
{
alter.ExecuteNonQuery();
}
using (var get = new OracleCommand(sql3, connection))
{
using (var reader = get.ExecuteReader())
{
Debug.WriteLine("Columns: " + reader.FieldCount);
// outputs 3, which is *wrong* <---- Here's the problem
}
}
using (var cols = new OracleCommand(sql4, connection))
{
using (var reader = cols.ExecuteReader())
{
int count = 0;
while (reader.Read())
{
count++;
Debug.WriteLine("Col: " + reader.GetString(0));
}
Debug.WriteLine("Columns: " + count.ToString());
// outputs 4, which is right
}
}
}
}
我已经尝试了一些方法来防止这种行为,但它们都没有给我返回第 4 列:
- 我关闭连接并重新打开它
- 我为
SELECT使用了一个新的OracleConnection,而不是ALTER - 我对@987654329@ 和
ALTER使用相同的OracleConnection - 我为
SELECT使用了一个新的OracleCommand,而不是ALTER - 我对@987654335@ 和
ALTER使用相同的OracleCommand - 我在
ALTER和SELECT之间的连接上调用PurgeStatementCache - 我在
ALTER和SELECT之间的连接上调用FlushCache - 我明确地将
Close和DisposeOracleCommand和OracleConnection(与使用块相对)用于ALTER和SELECT - 重新启动调用 PC 和托管 Oracle 数据库的 PC。
如果我通过SELECT * FROM all_tab_cols 查看列列表,则新列就在那里。
似乎唯一可靠的工作是关闭应用程序并重新启动它(它来自单元测试,但它是测试主机的关闭和重新启动)。然后我得到第四列。有时我可以使用断点并重新执行查询,然后会出现第 4 列,但没有任何东西可以通过直接执行代码来特别重复(意味着不设置断点并将执行点向上移动)。
ODAC 内部的某些东西似乎正在缓存该表的模式,但我可以弄清楚是什么、为什么或如何阻止它。任何人都有这方面的经验,或者有什么想法可以防止它吗?
【问题讨论】:
-
您是否尝试过在 SQL Developer 中发出“提交”语句?如果您没有明确发出提交,更新、插入和 ddl 更改将不会持续存在,它们只是处于一个打开的事务中,因为 SQL Developer 默认将它们包装在一个事务中。这是 SQL Server 的相反行为,您必须在提交之前定义事务。
-
刚试过。在 ALTER 和 SELECT 之间设置一个断点,运行到那个断点,在 SQL Developer 中执行 COMMIT,然后运行 SELECT,我仍然只能返回 3 列。
-
@DavidC 你不应该在做一个改变表(它是隐含的)之后发出提交,但我想已经发生了奇怪的事情。而且我不知道为什么这个问题被否决了,似乎比我在 Oracle 选项卡中看到的许多问题要好。 +1
-
odp.net 什么版本? (11.2 rel 5 是最新的,你在哪个?)
-
我用版本更新了问题。不知道为什么它也被否决了,这是一个真正的问题,在询问之前我已经做了一大堆的跑腿工作试图自己解决它。不过不要过分担心 - 我很确定我可以识别好问题和坏问题。