Проблема с получением счетчика в Access-e
От: Mondorro  
Дата: 19.02.07 05:16
Оценка:
Для многих это уже наверное избитая тема, а я с этим столкнулся впервые.
Есть таблица ключевое поле в которой счетчик, мне нужно получить значение счетчика для только что добавленной записи в таблицу.
Таблица у меня в Access-е, не использовал SQL потому что в нем нет необходимости уж слишком он громоздкий для моей задачки, а через dbf не умею
Я попробовал как советует Сеппа в "Microsoft ADO.NET" через событие Row.Updated, но "SELECT @@IDENTITY" выдает 0
ниже отрывок моего кода добавления записи в таблицу с попыткой извлечь значение счетчика:


public partial class Form1 : Form
    {
        string strConString = Procedures.strConectionString;
        OleDbConnection odbConString1 = null;
        OleDbCommand cmdGetIdentity = null;
        OleDbDataAdapter ClientName_DA;

        public Form1()
        {
            InitializeComponent();
            odbConString1 = new OleDbConnection(strConString);
            cmdGetIdentity = new OleDbCommand("SELECT @@IDENTITY", odbConString1);
        }

        void FillDB(string strName, string strAdress)
        {
            string strSQL = "SELECT ID, Cl_Name FROM ClientName";

            ClientName_DA = new OleDbDataAdapter(strSQL, odbConString1);
            ClientName_DA.RowUpdated += new OleDbRowUpdatedEventHandler(HandleRowUpdated);
            DataSet DS = new DataSet();
            ClientName_DA.Fill(DS, "ClientName");
            DataTable DT = DS.Tables["ClientName"];
            DT.PrimaryKey = new DataColumn[] { DT.Columns[0] };
            DT.Columns[0].AutoIncrement = true;
            DT.Columns[0].AutoIncrementSeed = -1;
            DT.Columns[0].AutoIncrementStep = -1;
            DataRow row =DT.NewRow();
            row[1] = strName;
            DT.Rows.Add(row);
            if (AcceptClientNameTableChangings(DT.Select("", "", DataViewRowState.Added)))
                Procedures.MessageWindow("Succsefully Added", 2, 1);           
                
        }

        private void HandleRowUpdated(object sender, OleDbRowUpdatedEventArgs e)
        {
            if ((e.Status == UpdateStatus.Continue) && (e.StatementType == StatementType.Insert))            
            {
                int index=(int)cmdGetIdentity.ExecuteScalar();
                e.Row["ID"] = index;
                MessageBox.Show("New index is "+index);
                e.Row.AcceptChanges();
            }
        }

        OleDbCommand InsertIntoClientNameTable()
        {
            string strSQL = "INSERT INTO ClientName (Cl_Name) VALUES (?)";
            OleDbConnection odbConString1 = new OleDbConnection(strConString);
            OleDbCommand cmd = new OleDbCommand(strSQL, odbConString1);
            OleDbParameterCollection pc = cmd.Parameters;
            pc.Add("@Cl_Name", OleDbType.VarChar, 0, "Cl_Name");

            return cmd;
        }

        public bool AcceptClientNameTableChangings(DataRow[] dRows)
        {
            try
            {
// если убрать принудительное открытие, то на запрос "SELECT @@IDENTITY" прога вылетает с ошибкой, 
// "подключение не открыто"
                odbConString1.Open(); 
                ClientName_DA.InsertCommand = InsertIntoClientNameTable();
                ClientName_DA.UpdateCommand = UpdateClientNameTable();
                ClientName_DA.DeleteCommand = DeleteFromClientNameTable();
                ClientName_DA.Update(dRows);
                odbConString1.Close();
                return true;
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "Ошибка!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        
        private void obAdd_Click(object sender, EventArgs e)
        {
            FillDB(otbName.Text, "");

        }
    }


ЗЫЖ: не судите строго Я только учусь
Re: Проблема с получением счетчика в Access-e
От: tyger Россия  
Дата: 19.02.07 09:09
Оценка:
Здравствуйте, Mondorro, Вы писали:

Если в открытой базе с помощью Access'а у тебя при добавлении строк у тебя инкрементится счетчик и сам добавляется, то
Смотри комментарий в тексте...

M>
M>public partial class Form1 : Form
M>    {
M>        string strConString = Procedures.strConectionString;
M>        OleDbConnection odbConString1 = null;
M>        OleDbCommand cmdGetIdentity = null;
M>        OleDbDataAdapter ClientName_DA;

M>        public Form1()
M>        {
M>            InitializeComponent();
//вот здесь, скорее всего надо использовать RecordSet, 
//потому как COmmand не возвращает результатов - он возвращает количество реально 
//обратотанных записей (или что-то в этом духе).
//т.е. вместо
M>            odbConString1 = new OleDbConnection(strConString);
M>            cmdGetIdentity = new OleDbCommand("SELECT @@IDENTITY", odbConString1);
//нужно написать(за синтаксис не ручаюсь -JScript, как правильно посмотришь в MSDN):
          odbConString1 = new OleDbConnection(strConString);
          rsGetIdentity = new OleDbRecordset("SELECT @@IDENTITY", odbConString1);
          if (!rsGetIdentity.BOF && rsGetIdentity.EOF)
          {
            int Identity = rsGetIdentity.Fields(0).Value;
          }
M>        }

M>        void FillDB(string strName, string strAdress)
M>        {
M>        }

M>        private void HandleRowUpdated(object sender, OleDbRowUpdatedEventArgs e)
M>        {
M>        }

M>        OleDbCommand InsertIntoClientNameTable()
M>        {
M>        }

M>        public bool AcceptClientNameTableChangings(DataRow[] dRows)
M>        {
M>            try
M>            {
M>        }
        
M>        private void obAdd_Click(object sender, EventArgs e)
M>        {
M>        }
M>    }

M>


M>ЗЫЖ: не судите строго Я только учусь
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Проблема с получением счетчика в Access-e
От: Аноним  
Дата: 20.02.07 04:57
Оценка:
Здравствуйте, tyger, Вы писали:

T>Здравствуйте, Mondorro, Вы писали:


T>Если в открытой базе с помощью Access'а у тебя при добавлении строк у тебя инкрементится счетчик и сам добавляется, то

T>Смотри комментарий в тексте...
Да в Access-е счетчик инкрементируется, но свои значения я туда не вписываю.


M>>        public Form1()
M>>        {
M>>            InitializeComponent();
T>//вот здесь, скорее всего надо использовать RecordSet, 
T>//потому как COmmand не возвращает результатов - он возвращает количество реально 
T>//обратотанных записей (или что-то в этом духе).
T>//т.е. вместо
M>>            odbConString1 = new OleDbConnection(strConString);
M>>            cmdGetIdentity = new OleDbCommand("SELECT @@IDENTITY", odbConString1);
T>//нужно написать(за синтаксис не ручаюсь -JScript, как правильно посмотришь в MSDN):
T>          odbConString1 = new OleDbConnection(strConString);
T>          rsGetIdentity = new OleDbRecordset("SELECT @@IDENTITY", odbConString1);
Но в C# нету OleDbRecordset...
И замену ему я не нашел или плохо искал
RecordSet это же вроде VB? Но в VB.Net такой функции тоже вроде как нет...
Куда копать? MSDN на этот счет вроде отмалчивается...

T>          if (!rsGetIdentity.BOF && rsGetIdentity.EOF)
T>          {
T>            int Identity = rsGetIdentity.Fields(0).Value;
T>          }
M>>        }
Re[2]: Проблема с получением счетчика в Access-e
От: Mondorro  
Дата: 20.02.07 05:07
Оценка:
Здравствуйте, tyger, Вы писали:

T>Здравствуйте, Mondorro, Вы писали:


T>Если в открытой базе с помощью Access'а у тебя при добавлении строк у тебя инкрементится счетчик и сам добавляется, то

T>Смотри комментарий в тексте...
Access у меня закрыт, и предполагается что юзер в дальнейшем не будет туда лазить для правки.
M>>        public Form1()
M>>        {
M>>            InitializeComponent();
T>//вот здесь, скорее всего надо использовать RecordSet, 
T>//потому как COmmand не возвращает результатов - он возвращает количество реально 
T>//обратотанных записей (или что-то в этом духе).
T>//т.е. вместо
M>>            odbConString1 = new OleDbConnection(strConString);
M>>            cmdGetIdentity = new OleDbCommand("SELECT @@IDENTITY", odbConString1);
T>//нужно написать(за синтаксис не ручаюсь -JScript, как правильно посмотришь в MSDN):
T>          odbConString1 = new OleDbConnection(strConString);
T>          rsGetIdentity = new OleDbRecordset("SELECT @@IDENTITY", odbConString1);
Но в C# нету OleDbRecordset...
И замену ему я не нашел или плохо искал
RecordSet это же вроде VB? Но в VB.Net такой функции тоже вроде как нет...
Куда копать? MSDN на этот счет вроде отмалчивается...
T>          if (!rsGetIdentity.BOF && rsGetIdentity.EOF)
T>          {
T>            int Identity = rsGetIdentity.Fields(0).Value;
T>          }
M>>        }
Re[3]: Проблема с получением счетчика в Access-e
От: tyger Россия  
Дата: 20.02.07 05:21
Оценка:
Здравствуйте, Mondorro, Вы писали:

T>>Если в открытой базе с помощью Access'а у тебя при добавлении строк у тебя инкрементится счетчик и сам добавляется, то

T>>Смотри комментарий в тексте...
M>Access у меня закрыт, и предполагается что юзер в дальнейшем не будет туда лазить для правки.
Я это говорил к тому, чтобы ты проверил, что в самой базе у тебя все правильно сделано — правильный тип у столбца выставлен.

Ясно, глянул я в MSDN...
Правильный вариант должен выглядеть так:
M>
M>>>        public Form1()
M>>>        {
M>>>            InitializeComponent();
using (OleDbConnection connection = new OleDbConnection(strConString))
    {
        OleDbCommand command = new OleDbCommand("SELECT @@IDENTITY", connection);

        connection.Open();
        OleDbDataReader reader = command.ExecuteReader();

        while (reader.Read())
        {
            int Identity = reader[0];
        }
        reader.Close();
    }

M>>>        }
M>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Проблема с получением счетчика в Access-e
От: Mondorro  
Дата: 22.02.07 03:56
Оценка:
Здравствуйте, tyger, Вы писали:

T>Ясно, глянул я в MSDN...

T>Правильный вариант должен выглядеть так:
Где ты это нашел? У меня вроде установлена MSDN, но я в ней видно искать совсем не умею...
        public Form1()
        {
            InitializeComponent();
using (OleDbConnection connection = new OleDbConnection(strConString))
    {
..............[пофиксино]...................
    }

}

Кстати если я в таком ввиде впишу в конструктор класса, то Identity сразу при загрузке 0 выдаст, так как добавления не было.
Запихал немного измененную конструкцию в RowUpdated все равно ноль.
ИМХО ExecuteReader и ExecuteScalar, особо не отличаются в плане возвращения данных. Грубо говоря Scalar одно значение вовзращает Reader-несколько.
ЗЫЖ Скажи где ты это в MSDN нарыл попробую сам поискать...
Re[5]: Проблема с получением счетчика в Access-e
От: Mondorro  
Дата: 22.02.07 04:14
Оценка:
M>Здравствуйте, tyger, Вы писали:

Нашел в MSDN-е, почти так же и у меня было. Но блин все равно 0!
Может дело в строке подключения для Access-a?

"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=test.mdb"
Re[5]: Проблема с получением счетчика в Access-e
От: tyger Россия  
Дата: 22.02.07 05:13
Оценка:
Здравствуйте, Mondorro, Вы писали:

M>Кстати если я в таком ввиде впишу в конструктор класса, то Identity сразу при загрузке 0 выдаст, так как добавления не было.

M>Запихал немного измененную конструкцию в RowUpdated все равно ноль.
M>ИМХО ExecuteReader и ExecuteScalar, особо не отличаются в плане возвращения данных. Грубо говоря Scalar одно значение вовзращает Reader-несколько.

Строка подключения у тебя правильная, разве что для острастки можешь добавить логин пароль....

"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+database_path+";User ID=Admin;Password=;"



Ниже кусок моего кода правда на JScript (ASP), но через ADO, т.е. суть использования должна быть тебе в принципе ясна...
Я думаю, что возврат @@IDENTITY — это работа JET-драйвера, и от языка или среды исполнения зависеть не должен...
Может ты коннекты закрываешь и открываешь каждый раз? Тогда @@IDENTITY потеряется...

if ( nn_client_id == 0)
{
  var cmdApp = Server.CreateObject("ADODB.Command");
  cmdApp.ActiveConnection = tp_conn;
  cmdApp.CommandText = "INSERT INTO clients (short_company_name,address,phone,phone1,info) "+
                       "VALUES ('"+sn_sh_company_name+"','"+sn_address+"','"+sn_phone+"','"+sn_phone1+"','"+sn_info+"');";
  cmdApp.Execute;
  cmdApp = null;

  var rsApp = Server.CreateObject("ADODB.Recordset");
  rsApp.Open("SELECT @@IDENTITY", tp_conn);
  if (!rsApp.BOF && !rsApp.EOF)
  {
    nn_client_id = Number(rsApp.Fields(0).Value);
    Response.Write ("<br/>Addeid client with code     = "+nn_client_id+"<br/>");
  }
  if (rsApp.State == adStateOpen)
  rsApp.Close;
  rsApp = null;
}//if (isNaN(nn_client_id ...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Проблема с получением счетчика в Access-e
От: Mondorro  
Дата: 22.02.07 05:59
Оценка:
Здравствуйте, tyger, Вы писали:

Передрал все один в один из MSDN-а и заработала СЦУКА!

Спасибо за советы. Сам бы дольше наверное докапывался до истины...
Сейчас буду разбираться где у меня косяк. Где-то теряется соединение как ты и сказал, Обновление проходит успешно, но вот индекс не получаю.
Судя по всему создаю много ненужных подключений.
Главное, что MSDN-овское работает, значит не пропаду.
Re[7]: Проблема с получением счетчика в Access-e
От: Mondorro  
Дата: 22.02.07 06:10
Оценка:
Здравствуйте, Mondorro, Вы писали:

M>Здравствуйте, tyger, Вы писали:


M>Передрал все один в один из MSDN-а и заработала СЦУКА!


M>Спасибо за советы. Сам бы дольше наверное докапывался до истины...

M>Сейчас буду разбираться где у меня косяк. Где-то теряется соединение как ты и сказал, Обновление проходит успешно, но вот индекс не получаю.
M>Судя по всему создаю много ненужных подключений.
M>Главное, что MSDN-овское работает, значит не пропаду.

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