Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Обновление данных


Автор: Nastya 27.9.2004, 19:01
Ситуация:
Есть объекты классов:ODBCConnection, ODBCDataAdapter, класса поражденного от DataSet, DataGrid.
Все они «повязаны» в результате чего у меня в гриде отображается содержимое таблицы, ReadOnly = false

После закрытия программы, данные не обновляются.
Добавляю строку
odbcDataAdapter1.Update(dataSet11,dataSet11.Tables[0].TableName);

Получаю ошибку времени исполнения
Update requires a valid InsertCommand when passed DataRow collection with new rows.
Как обновить данные непосредственно в DB и по какому событию сие лучше совершать, что бы при поступлении новых данных база всегда была «свеженькой»

Автор: Kurt 29.9.2004, 01:16
Оохх.. Виноват, совсем забыл.
Для того, чтобы вносить изменения (добавлять/редактировать/удалять) в БД, нужно определить соотв. команды DataAdapter (т.е. соответственно InsertCommand, UpdateCommand, DeleteCommand).
Я буду говорить об InsertCommand, однако, несложно будет додумать код для остальных команд.
Пусть у нас есть таблица myTable с двумя столбцами intColumn и strColumn. По названиям ясно, каков тип этих столбцов.
Итак, сначала создаем InsertCommand:
Код

..
OleDbConnection cn = new OleDbConnection();
OleDbDataAdapter dAdapter = new OleDataAdapter(...);
..
dAdapter.InsertCommand = new OleDbCommand("insert into myTable (intColumn, strColumn) values (@intColumn,@strColumn)",cn);
..

Т.е. мы определили.. хм.. ну скажем, шаблон команды вставки строки.
Теперь мы должны определить вставляемые параметры:
Код

..
OleDbParameter param;
 
 param = dAdapter.InsertCommand.Parameters.Add(new OleDbParameter("@intColumn",OleDbType.Integer));
 param.SourceColumn = "intColumn";
 param.SourceVersion = DataRowVersion.Current;

 param = dAdapter.InsertCommand.Parameters.Add(new OleDbParameter("@strColumn",OleDbType.VarChar));
 param.SourceColumn = "strColumn";
 param.SourceVersion = DataRowVersion.Current;
..

Т.е. мы сопоставляем имя столбца с соотв. переменной в SQL-запросе, а также указываем тип столбца.
Все. После этого мы можем добавлять новые записи (dAdapter.Update(..)).
Для обновления/удаления существующих записей, нам надо лишь правильно составить запрос и определить соотв. параметры.
По-хорошему, в каждой программе следует определять все команды DataAdapter'a (InsertCommand, UpdateCommand, DeleteCommand, SelectCommand)
Дальше все сделает Update().

P.S.
На всякий случай, вот полная программка, к-я выводит содержание вышеописанной таблицы, потом делает вставку строк и выводит обновленные данные. (данные заново качаются с базы, а перед этим DataSet очищается..). Написано немного криво, извиняйте, сейчас маловато времени.. sad.gif
Код

using System;
using System.Data;
using System.Data.OleDb;

class MainClass
{

//вспомогательный метод - распечатывает таблицу
private static void PrintTable(DataSet ds, string tableName)
{
 Console.WriteLine(tableName+":");
 DataTable tbl = ds.Tables[tableName];
 for(int currentColumn=0; currentColumn<tbl.Columns.Count; currentColumn++)
 {
  Console.Write(tbl.Columns[currentColumn].ColumnName.Trim()+"\t");
 }
 Console.WriteLine();
 for(int currentRow=0; currentRow<tbl.Rows.Count; currentRow++)
 {
  for(int currentColumn=0; currentColumn<tbl.Columns.Count; currentColumn++)
  {
   Console.Write(tbl.Rows[currentRow][currentColumn].ToString().Trim()+"\t");
  }
  Console.WriteLine();
 }
 
 return;
}

public static void Main(string[] args)
{
 Console.WriteLine("Connecting to database.");
 OleDbConnection cn = new OleDbConnection();
 cn.ConnectionString = "Provider = Microsoft.Jet.OLEDB.4.0;"+@"data source=baza.mdb";
 cn.Open();
 string sqlSelect = "select * from myTable";
 OleDbDataAdapter dAdapter = new OleDbDataAdapter(sqlSelect, cn);
 dAdapter.InsertCommand = new OleDbCommand("insert into myTable (intColumn, strColumn) values (@intColumn,@strColumn)",cn);
 OleDbParameter param;
 
 param = dAdapter.InsertCommand.Parameters.Add(new OleDbParameter("@intColumn",OleDbType.Integer));
 param.SourceColumn = "intColumn";
 param.SourceVersion = DataRowVersion.Current;

 param = dAdapter.InsertCommand.Parameters.Add(new OleDbParameter("@strColumn",OleDbType.VarChar));
 param.SourceColumn = "strColumn";
 param.SourceVersion = DataRowVersion.Current;
 
 DataSet ds = new DataSet("myDataSet");
 try
 {
  dAdapter.Fill(ds, "myTable");
 }
 catch(Exception ex)
 {
  Console.WriteLine(ex.Message);
 }
 Console.WriteLine("Before..");
 PrintTable(ds,"myTable");
 DataRow myRow;
 for (int i=0; i<3; i++)
 {
  myRow = ds.Tables["myTable"].NewRow();
  myRow["intColumn"] = i;
  myRow["strColumn"] = "It works!";
  ds.Tables["myTable"].Rows.Add(myRow);
 }
 try
 {
  dAdapter.Update(ds,"myTable");
  ds.Dispose();
  ds = new DataSet();
  dAdapter.Fill(ds,"myTable");
  PrintTable(ds,"myTable");
 }
 catch(Exception ex)
 {
  Console.WriteLine(ex.Message);
 }
 finally
 {
  cn.Close();
 }

 
 Console.Read();
 Console.Read();
}
}


Автор: Nastya 30.9.2004, 20:01
Спасибо, но либо я что-то не поняла.
Я все делаю при помощи редактора ресурсов 2003 студии.
Получаю следующий код
Код

//
// odbcConnection1
//
his.odbcConnection1.ConnectionString = "DSN=fuel;UID=SYSDBA;DB=FUEL.GDB;PWD=mk";
//
// odbcDataAdapter1
//
this.odbcDataAdapter1.InsertCommand = this.odbcCommand1;
this.odbcDataAdapter1.SelectCommand = this.odbcSelectCommand1;
this.odbcDataAdapter1.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] {   new System.Data.Common.DataTableMapping("Table", "Table", new System.Data.Common.DataColumnMapping[] {new System.Data.Common.DataColumnMapping("ID", "ID"),new System.Data.Common.DataColumnMapping("NAME", "NAME")})});
//
// odbcCommand1
//
this.odbcCommand1.CommandText = "INSERT INTO SUB_UNIT(ID, NAME) VALUES (:ID, :NAME)";
this.odbcCommand1.Connection = this.odbcConnection1;
this.odbcCommand1.Parameters.Add(new System.Data.Odbc.OdbcParameter("ID", System.Data.Odbc.OdbcType.Int));
this.odbcCommand1.Parameters.Add(new System.Data.Odbc.OdbcParameter("NAME", System.Data.Odbc.OdbcType.NVarChar, 50));
//
// odbcSelectCommand1
//
this.odbcSelectCommand1.CommandText = "SELECT SUB_UNIT.* FROM SUB_UNIT";
this.odbcSelectCommand1.Connection = this.odbcConnection1;
//
// dataSet11
//
this.dataSet11.DataSetName = "DataSet1";
this.dataSet11.Locale = new System.Globalization.CultureInfo("en-US");
//
// dataGrid1
//
this.dataGrid1.DataMember = "";
this.dataGrid1.DataSource = this.dataSet11._Table;
this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
this.dataGrid1.Location = new System.Drawing.Point(8, 16);
this.dataGrid1.Name = "dataGrid1";

@ заменнена на : т.к. в интербейсе параметры передаются именно так (а моя база данных именно интербейсовская).
В результате имею ошибку времени исполенияни .
Подозреваю, что это связанно с тем, что не передаются инсерту параметры, может надо гд-то указывать кто и как их заполняет?

ОЧЕНЬ ОЧЕНЬ НУЖНА ПОМОЩЬ!

Автор: arilou 30.9.2004, 21:38
Цитата(Nastya @ 30.9.2004, 20:01)
@ заменнена на : т.к. в интербейсе параметры передаются именно так (а моя база данных именно интербейсовская).

Подозреваю, что именно это и вызывает проблемы. А нельзя "@" заменить на "?" ? Либо не использовать дизайнер VS 2003?

Автор: Kurt 30.9.2004, 22:59
arilou, я вот тоже об этом подумал...
Блин, что же может быть не так..
Nastya
Вот смотри, я прикрепил ftp://[email protected]/Kurt/dotNET/raznoe/for_ODBC0.zip(username=serega password=serega) с VS2003-проектом, к-й представляет собой маленькую форму с таблицей, и тремя кнопками:
"Load from DB" - загрузить данные из базы
"Save to DB" - сохранить данные в базу
"Close it!" - закрыть это супер приложение. smile.gif

Используется Access-база через ODBC. (.mdb прилагается. Располагается в папке Debug, рядом с exe) В базе всего одна таблица table1 с двумя столбцами c1 (Int), c2 (varchar). c1 Объявлен как Primary Key.
Сначала попробуй с Access.
Открой приложение в VS, поменяй ConnectionString (измени путь к базе baza0.mdb) и запускай. Кнопкой "Load.." загрузи данные в таблицу, внеси какие-нибудь изменения (лучше с c2, т.к. с1 должен быть всегда уникален). После этого нажми "Save to DB". Поидее все твои изменения сохранятся в базу. Проверить это ты можешь:
1) открыв базу в Access;
2) заново запустив приожение;
3) снова нажав "Load from DB" - это обновит таблицу.
Собственно, как делалось это великое приложение:
Как только я добавил DataAdapter и определил все поля, студия создала за меня SelectCommand и InsertCommand (НО И НЕ БОЛЕЕ!). Т.е. я запускаю приложение, могу добавлять новые записи, но при попытке удаления или редактирования - вываливаюсь в исключение, т.к. эти операции не определены.
Вручную добавляю два OdbcCommand с именами UpdateComm и DeleteComm. Щелчками мышки определяю им параметры и соотв. SQL-запросы. Назначаю их DataAdapter'у соотв. на UpdateCommand и DeleteCommand. Все. Хеппи энд. Все работает. smile.gif
Можно порассуждать, почему не определются комманды удаления и редактирования самой студией. Возможно, эти операции слишком зависят от конкретных условий разработки и структуры БД.
Хочу извиниться за несколько корявый стиль приложения - я не привык такие вещи делать в студии (notepad.exe форева smile.gif), но думаю, общий смысл понятен.
Вобщем, что тебе советую сделать:
1) скачать и распаковать приложение;
2) открыв в VS2003 изменить ConnectionString согласно тому, куда ты все это распакуешь.
3) запустить и поработать с Access'ом - если будет правильно указан ConnectionString, проблем не должно быть.
4) убедившись, что все работает, создать в Interbase точно такую же таблицу и, изменив опять ConnectionString, попробовать еще раз запустить.

Если с Access'ом не будет получаться - спрашивай, хотя проблем не должно быть.
Если не будет получаться именно с Interbase - тут я ничего не могу сказать. У меня нет ODBC-драйвера. Надо будет качать драйвер (кстати, попробуй специальный .NET-драйвер, о котором я говорил...)
И, наконец, если все работает - на здоровье. smile.gif

P.S. Сам я почти не пользуюсь Access, но он наиболее удобен в данном случае.
P.S.S. Пользуясь случаем, хочу поблагодарить за халявный ftp. smile.gif
Если будут проблемы с закачкой, зайдите на
195.131.88.214
имя serega
пароль serega
и пройдите к папке Kurt/dotNET/raznoe/

Автор: Nastya 4.10.2004, 18:34
Курт Огромное спасибо!!
Все заработало.
Я во первых перед Update не открывала коннект,
а во втоых не надо было писать имена параметров в запросе а заменить их "?"

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