Я использую Oracle ODAC.NET для проекта .NET 3.5 против базы данных Oracle 11 Express, и я вижу поведение, которое я не могу объяснить (и, похоже, не работает).ODAC, похоже, кэширует схему таблицы?
ODAC должен быть последним, я просто вытащил его 3 дня назад, но версии таковы:
- Oracle.DataAccess.dll версия 2.112.3.0 (выпуск 5)
- oci.dll (клиент мгновенного) версии 11.2.0.1
у меня есть таблица, люди, что имеет 3 колонки:
- ID
- FirstName
- LastName
В коде я запускаю команду ALTER TABLE, используя OracleCommand.ExecuteNonQuery
, чтобы добавить новый столбец с именем "MIDDLE_NAME" к столу. Эта команда преуспевает. Если я посмотрю на таблицу с Oracle SQL Developer, появятся столбцы. Все хорошо и хорошо.
Теперь, если я бегу использовать 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-й столбец:
- Я закрываю соединение и повторно открыть его
- Я использую новый
OracleConnection
дляSELECT
чем дляALTER
- Я использую тот же
OracleConnection
дляSELECT
и дляALTER
- Я использую новый
OracleCommand
дляSELECT
чем дляALTER
- я использую тот же
OracleCommand
дляSELECT
и дляALTER
- Я называю
PurgeStatementCache
на связи междуALTER
иSELECT
- Я называю
FlushCache
на связи междуALTER
иSELECT
- я явно
Close
иDispose
OracleCommand
иOracleConnection
(в отличие от, используя блок), используемые дляALTER
иSELECT
- перезапущены вызывающие ПК и ПК хостинга базы данных Oracle.
Если я смотрю на список столбцов, выполнив SELECT * FROM all_tab_cols
, там будет новый столбец.
Единственное, что работает надёжно, - это закрыть приложение и перезапустить его (ну, это из единичного теста, но это остановка и перезапуск тестового узла). Затем я получаю эту четвертую колонку. Иногда я могу использовать точки останова и повторно выполнять запросы, и появится 4-й столбец, но ничего, что можно повторить с прямым выполнением кода (что означает без установки точки останова и перемещения точки выполнения).
Что-то в недрах ODAC, похоже, кэширует схему этого стола, но я могу выяснить, что, почему и как предотвратить это. У кого-нибудь есть опыт с этим или идеи, как я могу это предотвратить?
Вы пробовали оформив "Commit" заявление в SQL Developer? Если вы не вносите явные изменения в фиксацию, обновления, вставки и ddl не будут сохраняться, они просто сидят в открытой транзакции, так как SQL Developer обертывает их по умолчанию. Это противоположное поведение SQL Server, где вы должны определить транзакцию перед фиксацией. –
Просто попробовал. Положите точку разрыва между ALTER и SELECT, побежали к этому перерыву, сделали COMMIT в SQL Developer, затем запустили SELECT, и я все еще возвращаю только 3 столбца. – ctacke
@DavidC вам не нужно вызывать фиксацию после выполнения таблицы alter (ее неявной), но, похоже, что-то странное. И я не знаю, почему этот вопрос получил downvote, кажется лучше, чем многие, которые я вижу на вкладках Oracle.+1 – tbone