Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Базы данных под .NET > Сохранение результатов запроса к Interbase в DBF


Автор: XavierElf 6.8.2007, 09:15
В общем возникла такая проблема: нужно сохранить результаты запроса к базе типа Interbase/Firebird в DBF. По форуму поискал, но что-то ничего путного не нашёл. Есть отдельно подключение к GDB базе, есть отдельно к DBF таблице(файлу), а так чтобы связать их - нету. Суть заключается в следующем:
Примерный запрос к GDB базе:
Код

SELECT DISTINCT
    Table1.ID_Table1,
    Table2.CLCS104_Table2,
    Table3.SVALUE,
    Table4.FLDS001_Table4,
    Table1.FLDS001_Table1,
    Table1.FLDD002_Table1,
    Table1.FLDS003_Table1,
    Table1.FLDS004_Table1,
    Table5.FLDN010_Table5,
    Table1.FLDN101_Table1,
    Table1.FLDN020_Table1,
    0 FLDN,
    Table1.PACK
FROM Table1
    INNER JOIN Table2 ON (Table1.LNK_Table2 = Table2.ID_Table2)
    INNER JOIN Table4 ON (Table2.REF203_Table4 = Table4.ID_Table4)
    INNER JOIN Table3 ON (Table4.REF_Table31010 = Table3.ID_Table3)
    INNER JOIN Table5 ON (Table1.ID_Table1 = Table5.REF_Table6)
WHERE (
    (Table5.REF_Table7 = 500340)
and
    (Table5.FLDN010_Table5 > 0))
ORDER BY Table2.CLCS104_Table2, Table3.SVALUE, Table4.FLDS001_Table4,
    Table5.FLDN010_Table5

DBF файл используется только для сохранения результатов этого запроса, причём каждый раз создаётся заново а не дополняется.
Кто скалкивался с подобным посоветуйте плз, как реализовать?

Автор: LuMee 6.8.2007, 11:22
А в чем конкретно проблема? Выгружаем данные из Interbase в DataTable, потом создаем dbf-файлик и с помощью DataAdapter'a данные в него выгружаем. В лицах сохранение будет выглядеть наподобие такого:
Код

// получили табилцу с данными
DataTable dataTable = ...
string dbfConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Каталог в котором будет dbf-ка;Extended Properties=dBASE IV;User ID=Admin;Password=;"
// команда на создание dbf'а
string createTableSql = "CREATE TABLE ...";
using (OleDbConnection connection = new OleDbConnection(dbfConnectionString))
{
        OleDbCommand createCommand = connection.CreateCommand();
        createCommand.CommandText = createTableSql;

        connection.Open();
        command.ExecuteNonQuery();

        OleDbCommand insertCommand = "INSERT INTO ... VALUES(?, ?, ...)";
        insertCommand.Parameters.Add("ColumnName1", OleDbType.VarChar);
        ... // и так далее, по числу полей

        OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
        dataAdapter.InsertCommand = insertCommand;
        dataAdapter.Update(dataTable);
 }

Автор: XavierElf 6.8.2007, 11:30
Не совсем понятен смысл этого:
Цитата(LuMee @  6.8.2007,  11:22 Найти цитируемый пост)
Код

OleDbCommand insertCommand = "INSERT INTO ... VALUES(?, ?, ...)";
insertCommand.Parameters.Add("ColumnName1", OleDbType.VarChar);
... // и так далее, по числу полей
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
dataAdapter.InsertCommand = insertCommand;

В результате выполнения вышеуказанного запроса формируется прайс на 5000 наименований. Не вижу реального смысла использования команды INSERT. Тем более никаких изменений в таблице DataTable после получения в неё результатов запроса не должно быть. Она должна быть сохранена в DBF в том видеб в котором есть.

Автор: LuMee 6.8.2007, 14:17
Не, ну INSERT-команда адаптеру полюбому нужна, чтобы он знал, как правильно данные сохранять. Можно попробовать без нее, вдруг догадается использовать названия полей DataTable'а (хотя сомневаюсь), тогда только надо будет ему connection string объяснить.
P.S. да, под фразой "по числу полей" я подразумевал не 5000 наименований, а "по числу столбцов полученной выборки" smile

Автор: XavierElf 6.8.2007, 14:30
Так я в принципе разобрался, решил попробовать таким образом:
Код

string insertQuery = "";
for (int i = 0; i < priceDS.Tables["cprc"].Rows.Count; i++)
{
    insertQuery +=
        "INSERT INTO cprc.dbf(" +
            "ID_Table1, CLCS104_Table2, SVALUE, FLDS001_Table4, FLDS001_Table1," +
            "FLDD002_Table1, FLDS003_Table1, FLDS004_Table1, FLDN010_Table5, " +
            "FLDN101_Table1, FLDN020_Table1, FLDN, PACK) " +
        "VALUES(" +
            priceDS.Tables["cprc"].Rows[i].ItemArray[0].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[1].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[2].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[3].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[4].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[5].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[6].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[7].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[8].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[9].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[10].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[11].ToString() + ", " +
            priceDS.Tables["cprc"].Rows[i].ItemArray[12].ToString() + ");";
}
OleDbConnection conToDbf = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\\somedir\\;Extended Properties=dBASE IV;User ID=Admin;Password=");
OleDbTransaction dbfTrans;
OleDbCommand dbfCmd = new OleDbCommand(insertQuery, conToDbf, dbfTrans);
try
{
    conToDbf.Open();
}
catch (OleDbException dbfEx)
{
    myLog.WriteEntry(dbfEx.Message.ToString());
}
dbfTrans = conToDbf.BeginTransaction();
dbfCmd.ExecuteNonQuery();
dbfTrans.Commit();


ЗЫЖ Создание dbf файла не стал указывать, это не так сложно...
ЗЗЫЖ Сейчас опробую этот код и скажу результат.

Автор: XavierElf 6.8.2007, 15:43
Что-то не проходит эта команды выдаётся ошибка:
Цитата

Обнаружены символы за пределами инструкции SQL.

Что бы это могло значить - непонятно...

Автор: LuMee 7.8.2007, 07:36
Цитата(XavierElf @ 6.8.2007,  15:43)
Что-то не проходит эта команды выдаётся ошибка:
Цитата

Обнаружены символы за пределами инструкции SQL.

Что бы это могло значить - непонятно...

Надо посмотреть отладчиком, какой получается запрос. Вероятно, в каком-то поле выборки попалась, скажем, скобка или еще чего, в результате чего запрос получился кривой. Потому, собственно, и рекомендовал делать через параметры, тем более что полей в выборке вроде не так много.

Автор: XavierElf 8.8.2007, 10:15
Сделал таким образом:
Код

            OleDbConnection conToDbf2 = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\\AlphaFTPWork\\Price\\;Extended Properties=dBASE IV;User ID=Admin;Password=");

            #region insertQuery
            OleDbCommand insertQuery = conToDbf2.CreateCommand();
            insertQuery.CommandText = "INSERT INTO cprc.dbf(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am) " +
                     "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?);";
            insertQuery.Parameters.Add("aa", OleDbType.Numeric);
            insertQuery.Parameters.Add("ab", OleDbType.Char);
            insertQuery.Parameters.Add("ac", OleDbType.Char);
            insertQuery.Parameters.Add("ad", OleDbType.Char);
            insertQuery.Parameters.Add("ae", OleDbType.Char);
            insertQuery.Parameters.Add("af", OleDbType.DBDate);
            insertQuery.Parameters.Add("ag", OleDbType.Char);
            insertQuery.Parameters.Add("ah", OleDbType.Char);
            insertQuery.Parameters.Add("ai", OleDbType.Numeric);
            insertQuery.Parameters.Add("aj", OleDbType.Numeric);
            insertQuery.Parameters.Add("ak", OleDbType.Numeric);
            insertQuery.Parameters.Add("al", OleDbType.Numeric);
            insertQuery.Parameters.Add("am", OleDbType.Char);
            #endregion

            conToDbf2.Open();
            OleDbDataAdapter dbfAdapter = new OleDbDataAdapter("select * from cprc.dbf", conToDbf2);
            dbfAdapter.InsertCommand = insertQuery;
            dbfAdapter.Update(priceDS.Tables["cprc"]);
            conToDbf2.Close();

Не экспортирует в dbf. Уже даже не знаю как быть... :(

Автор: LuMee 8.8.2007, 11:02
Цитата(XavierElf @ 8.8.2007,  10:15)
Не экспортирует в dbf. Уже даже не знаю как быть... :(

А что за ошибку пишет?

Автор: XavierElf 8.8.2007, 11:21
Да в том-то и дело, что он даже ошибки не выдаёт...

Автор: LuMee 8.8.2007, 11:29
Просто ничего не добавляет что ли получается? А у тебя названия параметров в INSERT-запросе и названия столбцов в сохраняемом DataTable одинаковые?

Автор: XavierElf 8.8.2007, 12:13
Одинаковые. Самое интересное, что запрос INSERT не хочет выполняться даже для самой примитивной таблицы...

Автор: LuMee 8.8.2007, 13:09
Ну тогда остается генерить INSERT-запрос самостоятельно и пробовать его выполнять, типа такого:
Код

// обращаем внимание на кавычки вокруг {1} - это для текстовых полей
string pattern = "INSERT INTO Tab (FieldA, FieldB, ...) VALUES ({0}, '{1}', ...)";
OleDbCommand command = new OleDbCommand(oleConnection);
foreach(DataRow row in dataTable.Rows)
{
    command.CommandText = string.Format(pattern, row["FieldA"], row["FieldB"], ...);
    command.ExecuteNonQuery();
} 

Автор: XavierElf 8.8.2007, 13:57
Теперь он часть таблицы заполняет, а на другую часть выдаёт:
"Не совпадает число значений запроса и число результирующих полей."

Автор: LuMee 8.8.2007, 14:09
Что значит "часть таблицы"? В смысле, 10 записей добавил, а на 11ю сказал вышеозначенное сообщение? Если так, то вероятно где то в DataTable попался DBNull - нужно в этом месте писать в INSERT-запрос NULL. Посмотри отладчиком, как выглядит запрос, вызывающий ошибку

Автор: XavierElf 8.8.2007, 14:34
с этим разобрался. просто все {0}, {1} ... и т.д. заключил в апострофы. однако теперь вопрос который у меня возник сначала и я его оставил на потом: почему когда я создаю таблицу и в ней поля типа NUMERIC вне зависимости от того, как я напишу (NUMERIC(11) или NUMERIC(11,0) или NUMERIC(11, 3)) у меня всегда создаются поля размерности 20 и точности 5. Почему?

Автор: LuMee 9.8.2007, 07:53
Ну, это уже вопрос непростой... Возможно, тут дело в каких-то особенностях драйвера OLE DB для dbf. Если это так критично, то можно попробовать поискать другие драйверы и компоненты для доступа к dbf из .NET. Хотя на мной взгляд, лучше больше, чем лучше. Главное - все данные сохранятся без потерь точности.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)