2016-07-02 2 views
1

Я работаю над приложением для управления счетами, которое извлекает информацию из базы данных Access (современный формат .accdb) и обеспечивает корректную работу данных, но когда я пытаюсь ее обновить (следуя некоторым учебным пособиям или я должен сказать, ответы, ничего не работает .. Что не так с этим кодом, он ... должен работатьОбновление строки таблицы с OleDB с C#

public int UpdateDBBill(Bill bill) 
    { 
     using (var connection = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\BC.accdb")) 
     using (var command = connection.CreateCommand()) 
     { 
      connection.Open(); 

      command.CommandType = CommandType.Text; 
      command.CommandText = "UPDATE Bills SET Payer = @Payer, Category = @Category, Recipient = @Recipient, Currency = @Currency, Amount = @Amount, IBANOfRecipient = @IBANOfRecipient, Model = @Model, ReferenceNumber = @ReferenceNumber, Description = @Description, DueDate = @DueDate, ForMonth = @ForMonth, Paid = @Paid, DatePaid = @DatePaid WHERE Id = @Id"; 

      command.Parameters.AddWithValue("@Payer", bill.Payer); 
      command.Parameters.AddWithValue("@Category", bill.Category); 
      command.Parameters.AddWithValue("@Recipient", bill.Recipient); 
      command.Parameters.AddWithValue("@Currency", bill.Currency); 
      command.Parameters.AddWithValue("@Amount", bill.amount); 
      command.Parameters.AddWithValue("@IBANOfRecipient", bill.IBANOfRecipient); 
      command.Parameters.AddWithValue("@Model", bill.Model); 
      command.Parameters.AddWithValue("@ReferenceNumber", bill.ReferenceNumber); 
      command.Parameters.AddWithValue("@Description", bill.Description); 
      command.Parameters.AddWithValue("@DueDate", bill.DueDate); 
      command.Parameters.AddWithValue("@ForMonth", bill.ForMonth); 
      command.Parameters.AddWithValue("@Paid", bill.Paid); 
      command.Parameters.AddWithValue("@DatePaid", bill.DatePaid); 
      command.Parameters.AddWithValue("@Id", bill.Id); 

      try 
      { 
       return command.ExecuteNonQuery(); 
      } 
      catch 
      { 
       return -1;//for error 
      } 
     } 
    } 

Ответ:.

public int UpdateDBBill(Bill bill) 
    { 
     using (var connection = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\BC.accdb")) 
     using (var command = connection.CreateCommand()) 
     { 
      connection.Open(); 

      command.CommandType = CommandType.Text; 

      command.CommandText = "UPDATE Bills SET Payer = @Payer, Category = @Category, Recipient = @Recipient, [Currency] = @Currency, Amount = @Amount, IBANOfRecipient = @IBANOfRecipient, [Model] = @Model, ReferenceNumber = @ReferenceNumber, DueDate = @DueDate, ForMonth = @ForMonth, Paid = @Paid, DatePaid = @DatePaid WHERE Id = @Id"; 
      command.Parameters.Add("@Payer", OleDbType.VarChar).Value = bill.Payer; 
      command.Parameters.Add("@Category", OleDbType.VarChar).Value = bill.Category; 
      command.Parameters.Add("@Recipient", OleDbType.VarChar).Value = bill.Recipient; 
      command.Parameters.Add("@Currency", OleDbType.VarChar).Value = bill.Currency; 
      command.Parameters.Add("@Amount", OleDbType.VarChar).Value = bill.GetAmount(); 
      command.Parameters.Add("@IBANOfRecipient", OleDbType.VarChar).Value = bill.IBANOfRecipient; 
      command.Parameters.Add("@Model", OleDbType.VarChar).Value = bill.Model; 
      command.Parameters.Add("@ReferenceNumber", OleDbType.VarChar).Value = bill.ReferenceNumber; 
      command.Parameters.Add("@DueDate", OleDbType.Date).Value = bill.DueDate.Date; 
      command.Parameters.Add("@ForMonth", OleDbType.Date).Value = bill.ForMonth.Date; 
      command.Parameters.Add("@Paid", OleDbType.Boolean).Value = bill.Paid; 
      command.Parameters.Add("@DatePaid", OleDbType.Date).Value = bill.DatePaid.Date; 
      command.Parameters.Add("@Id", OleDbType.Integer).Value = bill.Id; 

      try 
      { 
       int Rows = command.ExecuteNonQuery(); 
       return Rows; 
      } 
      catch 
      { 
       return -1;//for error 
      } 
     } 
    } 

ответ

4

с OleDb положения вопросов параметров много.
OleDb не связывает метки-заполнители параметров с именами параметров, а следует строго позиционным порядком. Таким образом, ваш запрос верен, но когда вы добавляете параметры в коллекцию, вы должны следовать порядку запаса параметров.

command.CommandType = CommandType.Text; 
command.CommandText = "UPDATE Bills SET ([Payer] = @Payer, [Category] = @Category, ...) WHERE Id = @Id"; 
command.Parameters.AddWithValue("@Payer", bill.Payer); 
command.Parameters.AddWithValue("@Category", bill.Category); 
.... 
command.Parameters.AddWithValue("@Id", bill.Id); 

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

В качестве примечания следует учитывать, что AddWithValue - удобный, но опасный метод. Тип параметра извлекается значение, переданное и иногда это может создать «DataType несоответствие Exception» или неправильные преобразования (в частности, если вы передаете даты или десятичных знаков в виде строки в AddWithValue)

См Can we stop using AddWithValue already?

EDIT После долгого отладочного сеанса в чате окончательная проблема идентифицируется в поле «Валюта», написанном с помощью скобок. Валюта - это зарезервированные слова в Access и должна быть заключена в квадратную скобку. Это не было изначально очевидно, потому что первый запрос, предложенный OP, был правильно напечатан с квадратной скобкой, но тогда по какой-либо причине квадратные скобки исчезли из запроса. Предложение не использовать AddWithValue стоит, чтобы избежать ненужных преобразований из дат в строки, а затем обратно в строки ....

command.CommandText = "UPDATE Bills SET ([Payer] = @Payer, [Category] = @Category, ...) WHERE Id = @Id"; 
command.Parameters.Add("@Payer", OleDbType.VarWChar).Value = bill.Payer; 
command.Parameters.Add("@Category", OleDbType.VarWChar).Value = bill.Category; 
.... 
command.Parameters.Add("@DueDate", OleDbType.Date).Value = bill.DueDate.Date; 
.... 
command.Parameters.Add("@Id", OleDbType.Integer).Value = bill.Id; 
+0

Это правильный ответ. –

+0

Я пробовал это раньше, и это не сработало. то я перешел к тому, как теперь работает мой код, который тоже не работает. После вашего ответа я попытался добавить Id до конца еще раз, но я все еще получаю синтаксис с ошибкой оператора SQL. – DethoRhyne

+0

Тогда вам лучше показать весь текст команды и весь список параметров. Невозможно сказать, что такое синтаксическая ошибка из этого фрагмента. – Steve

1

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

В вашем случае, поскольку ваше обновление продолжается с параметрами Payer, Category ..., Id, ваши AddWithValues ​​должны следовать одному и тому же порядку.

Надеюсь, это поможет

+0

Они в точном порядке. за исключением Id, который в db И параметры являются первыми, но в запросе он упомянут последним, так как он находится в разделе WHERE – DethoRhyne

+0

Это моя точка ... Вы не должны следовать порядку в таблице, а порядку в вашем запросе. Когда я проверяю, добавляется поле AddWithValue for Id, вместо этого должно появиться последнее –

+0

Понятно, но, как я уже говорил выше, это дает мне ту же ошибку. – DethoRhyne

1

Хорошо ... Я нашел проблему.

Прежде всего, вы должны поместить поле «Валюта» в скобки, потому что Access рассматривает его как тип данных, если это не так, и вы получаете синтаксическую ошибку.

После этого не сохраняйте все инструкции AddWithValue без изменений.

Наконец, добавив поля даты (DueDate, ForMonth и DatePaid), используйте ToString («yyyy-MM-dd»), чтобы Access интерпретировал значение как дату. Кроме того, проанализируйте поле суммы, чтобы удвоить.

Ниже приведена моя версия кода.Надеюсь, что это будет работать :)

command.CommandType = CommandType.Text; 
 
command.CommandText = "UPDATE Bills SET Payer = @Payer, Category = @Category, Recipient = @Recipient, [Currency] = @Currency, Amount = @Amount, IBANOfRecipient = @IBANOfRecipient, Model = @Model, ReferenceNumber = @ReferenceNumber, Description = @Description, DueDate = @DueDate, ForMonth = @ForMonth, Paid = @Paid, DatePaid = @DatePaid WHERE Id = @Id"; 
 

 
command.Parameters.AddWithValue("@Payer", bill.Payer); 
 
command.Parameters.AddWithValue("@Category", bill.Category); 
 
command.Parameters.AddWithValue("@Recipient", bill.Recipient); 
 
command.Parameters.AddWithValue("@Currency", bill.Currency); 
 
command.Parameters.AddWithValue("@Amount", Convert.ToDouble(bill.amount)); 
 
command.Parameters.AddWithValue("@IBANOfRecipient", bill.IBANOfRecipient); 
 
command.Parameters.AddWithValue("@Model", bill.Model); 
 
command.Parameters.AddWithValue("@ReferenceNumber", bill.ReferenceNumber); 
 
command.Parameters.AddWithValue("@Description", bill.Description); 
 
command.Parameters.AddWithValue("@DueDate", bill.DueDate.ToString("yyyy-MM-dd")); 
 
command.Parameters.AddWithValue("@ForMonth", bill.ForMonth.ToString("yyyy-MM-dd")); 
 
command.Parameters.AddWithValue("@Paid", bill.Paid); 
 
command.Parameters.AddWithValue("@DatePaid", bill.DatePaid.ToString("yyyy-MM-dd")); 
 
command.Parameters.AddWithValue("@Id", bill.Id); 
 

 
try 
 
{ 
 
    return command.ExecuteNonQuery(); 
 
} 
 
catch 
 
{ 
 
    return -1;//for error 
 
}

+0

Через длинный чат со Стивом мы придумали решение проблемы и пошли шаг за шагом. Валюта была проблемой, ей нужны скобки, а после этого с помощью 'command.Parameters.Add ("@Id", OleDbType.Integer) .Value = bill.Id; 'для указания типа формата для базы данных исправлены проблемы с датами и всего остального. но я благодарю вас за вашу работу, потому что это сработало! :) – DethoRhyne

Смежные вопросы