OleDbDataAdapter: cannot update database - c#

I've been working on this since yesterday and I just can't update my database.
There are 3 tables. Here is a piece of code of one of WinForms. It loads data and display but after changing sth manually in the grid I get either errors by calling Update or anything happens at all.
please help because I'm going crazy.
public partial class Form3 : Form
{
//instance fields
private export2Excel export2XLS;
private DataSet _dataSet;
private BindingSource _bsrc;
private OleDbDataAdapter _dAdapter;
private OleDbCommandBuilder _cBuilder;
private DataTable _dTable;
private void button1_Click(object sender, EventArgs e)
{
//create the connection string
string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source='C:\\Documents and Settings\\dorota\\Moje dokumenty\\Visual Studio
2010\\Projects\\WindowsFormsApplication1\\WindowsFormsApplication1\\artb.mdb'";
//create the database query
string query = "SELECT * FROM Samochody";
System.Data.DataSet DtSet = new System.Data.DataSet();
_dataSet = DtSet;
//create an OleDbDataAdapter to execute the query
OleDbDataAdapter dAdapter = new OleDbDataAdapter(query, connString);
dAdapter.FillSchema(_dataSet, SchemaType.Source);
_dAdapter = dAdapter;
//create a command builder
OleDbCommandBuilder cBuilder = new OleDbCommandBuilder(_dAdapter);
_cBuilder = cBuilder;
//create a DataTable to hold the query results
DataTable dTable = new DataTable();
_dTable = dTable;
//fill the DataTable
_dAdapter.Fill(_dTable);
//_dAdapter.TableMappings.Add("Samochody", "Table");
_dAdapter.Fill(_dataSet);
// --------------------- to datagridview !
//BindingSource to sync DataTable and DataGridView
BindingSource _bsrc = new BindingSource();
//set the BindingSource DataSource
//bSource.DataSource = _dTable;
_bsrc.DataSource = _dTable;
//_bsrc = bSource;
//set the DataGridView DataSource
dataGridView1.DataSource = _bsrc;
}
}
and here... :
private void sqlsave_Click(object sender, EventArgs e)
{
//int i=_dAdapter.Update(_dTable);
_dAdapter.Update(_dataSet.Tables["Samochody"]);
//_dAdapter.Update(_dataSet,"Samochody");
}
//---------------------------------------------------------------------------------
ok. I have changed sqlsave method for this
private void sqlsave_Click(object sender, EventArgs e)
{
try
{
//_dAdapter.Update(_dataSet.Tables["Samochody"]);
OleDbCommand oldb= _cBuilder.GetUpdateCommand();
int i=oldb.ExecuteNonQuery();
System.Windows.Forms.MessageBox.Show(i+" rows affected.");
//_dAdapter.Update(_dataSet,"Samochody");
}catch(OleDbException oldbex){
System.Windows.Forms.MessageBox.Show(oldbex.ToString());
}
and now I get finally sth more informative than "Error in"
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.Data.dll Additional information: ExecuteNonQuery
requires an open and available Connection. The connection's current
state is closed.
so let me changed sth and I will let you know if this is it!
//--------------------------------
no. no. too fast, can't last. now while trying to save I've got exception again,
connectin is opened, but (I can't post the image) when I debug this I see that my object of OleDbCommand type as _commandText has
"UPDATE Samochody SET Item=?, Data dyspozycji autem od=?, ..."
and so on.
I think this is the reason. Am I right? What to do?

You didn't provide a connection for your OleDbDataAdapter. Try it something like this:
The example is different from your code but it shows the declaration of New Connection and passing it to the OleDbDataAdapter
string connetionString = null;
OleDbConnection connection ;
OleDbDataAdapter oledbAdapter ;
OleDbCommandBuilder oledbCmdBuilder ;
DataSet ds = new DataSet();
int i = 0;
string sql = null;
connetionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Your mdb filename;";
connection = new OleDbConnection(connetionString);
sql = "select * from tblUsers";
try
{
connection.Open(); // your code must have like this
oledbAdapter = new OleDbDataAdapter(sql, connection);
oledbCmdBuilder = new OleDbCommandBuilder(oledbAdapter);
oledbAdapter.Fill(ds);
for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
ds.Tables[0].Rows[i].ItemArray[2] = "neweamil#email.com";
}
oledbAdapter.Update(ds.Tables[0]);
connection.Close();
MessageBox.Show ("Email address updates !");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}

I've found the answer:
But a better approach would be to use drag-and-drop and learn form the code.
Select Data|View Datasources. Your dataset should be visible in the DataSources Window.
Drag a table to a (new) form. VS2005 will add a load of components and a few lines of code.
The form will now have a instance of the dataset and that is your reference point for Adapter.Fill and .Update methods.
Easy and works great! : D
I've found it here: https://stackoverflow.com/a/548124/1141471

Related

Updating/saving data to an SQL database table using c# winforms

I'll start off by saying that I'm pretty inept at coding (have yet to learn how to utilize classes and how they work in depth), and that I've never worked with sql before doing this project.
The idea here is that you connect to an sql database, after which a datagridview element gets filled with data from a table called TABLE_1 by default. The user should then be able to input, delete and save data.
The first two work operations work perfectly, but the saving is the problem. I've banged my head against a wall for about 4 days trying to get the saving to work, but I just cant get it to do so. The saving is done with the method Button3_click.
Any insight as to what I should do?
Is the main chunk of the code where you connect the part where I'm
messing up?
//initialize the classes I guess, on some youtube guides they did so
SqlConnection con;
DataSet ds;
SqlDataAdapter a;
DataTable t;
SqlCommandBuilder scb;
static string tablename = "TABLE_1";
string constring;
//connect button
private void button1_Click(object sender, EventArgs e)
{
try
{
//connect using info from textboxes, connection is ok
constring = "server=" + Server.Text + ";database=" + DB.Text + ";UID=" + UID.Text + ";password=" + Password.Text;
SqlConnection con = new SqlConnection(constring);
con.Open();
DataSet ds = new DataSet();
Save.Enabled = true;
//check if table name is empty, if so default to TABLE_1
if (textBox1.Text != "")
{
tablename = textBox1.Text;
}
else
{
tablename = "TABLE_1";
}
a = new SqlDataAdapter("SELECT * FROM " + tablename, con);
DataTable t = new DataTable();
a.Fill(t);
datagrid.DataSource = t;
//
label5.Text = Server.Text;
con.Close();
}
catch(Exception es)
{
MessageBox.Show(es.Message);
}
}
//save button
private void button3_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(constring);
con.Open();
DataSet ds = new DataSet();
DataTable t = new DataTable();
a.TableMappings.Add(tablename, "t");
scb = new SqlCommandBuilder(a);
a.Update(t);
con.Close();
}
Use the following example which sets up the adapter, dataset and table name as private variables.
Also, I recommend to never use one letter variable names as a) it's difficult to debug b) when getting into more lines of code it's going to be difficult to know what a variable is for.
Next up, using SELECT *, it' unknown if you have setup a auto-incrementing primary key which is needed to perform updates. In the example below, Id is auto-incrementing.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsDataAdapterExample
{
public partial class Form1 : Form
{
private SqlDataAdapter _companiesSqlDataAdapter;
private DataSet _companiesDataSet;
private string _tableName = "Companies";
public Form1()
{
InitializeComponent();
Shown += OnShown;
}
private void OnShown(object sender, EventArgs e)
{
_companiesDataSet = new DataSet();
_companiesSqlDataAdapter = new SqlDataAdapter(
"SELECT Id, FirstName, LastName, PhoneNumber, City FROM dbo.Companies;",
"Data Source=.\\sqlexpress;Initial Catalog=ForumExample;" +
"Integrated Security=True");
var builder = new SqlCommandBuilder(_companiesSqlDataAdapter);
_companiesSqlDataAdapter.Fill(_companiesDataSet, _tableName);
dataGridView1.DataSource = _companiesDataSet.Tables[_tableName];
}
private void SaveButton_Click(object sender, EventArgs e)
{
_companiesSqlDataAdapter.Update(_companiesDataSet, _tableName);
}
}
}

how to select specific field using a filter from access in C#

in C# and windows Form,
I have a database like this:
and this is how I using a class put it's data into a datagridview:
class DBConnection
{
public static void GetList(Form2 frm2)
{
string DBPath = Application.StartupPath;
OleDbConnection Connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="+DBPath+#"\DataBase\SampleFeeds.accdb");
OleDbDataAdapter DataA = new OleDbDataAdapter("Select * from FeedLibrary", Connection);
DataTable Dtable = new DataTable();
DataA.Fill(Dtable);
frm2.SelectedFeeddataGridView.DataSource = Dtable;
}
}
and this is my form load:
private void Form2_Load(object sender, EventArgs e)
{
DBConnection.GetList(this);
}
So far everything is ok.
now I have a question:
for example I have a list box FeedSelectListBox,
I want to when user click on a button GrassLegumeForagebtn my FeedSelectListBox fill with only all of Feed Names that are in the category of Grass / Legume Forage.
how should I do that ?
with help of Damirchi My problem solved
//-----------------
But now I have another question:
I want to when user select a feed from list box all of it's data from data base (like name, number, feed type and ,,,) put in a data grid view.
I used this code on my SelectFeedbtn but it doesn't work :
private void SelectFeedbtn_Click(object sender, EventArgs e)
{
string StrCon = System.Configuration.ConfigurationManager.ConnectionStrings["FeedLibraryConnectionString"].ConnectionString;
OleDbConnection Connection = new OleDbConnection(StrCon);
string FeedSelectedID = FeedSelectListBox.SelectedValue.ToString();
OleDbDataAdapter DataA = new OleDbDataAdapter("Select * from FeedLibrary where ID = 'FeedSelectedID'" , Connection);
DataTable DTable = new DataTable();
DataA.Fill(DTable);
SelectedFeeddataGridView.DataSource = DTable;
}
And ValueMember property of FeedSelectListBox is ID but the error is :
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll.
I even use this query but it still doesn't work:
OleDbDataAdapter DataA = new OleDbDataAdapter("Select * from FeedLibrary where ID =" FeedSelectListBox.SelectedValue , Connection);
at first you most set the DisplayMember and ValueMember properties of FeedSelectListBox and use this code on click event.
you can put this code on GrassLegumeForagebtn click event.
string DBPath = Application.StartupPath;
OleDbConnection Connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="+DBPath+#"\DataBase\SampleFeeds.accdb");
OleDbDataAdapter DataA = new OleDbDataAdapter("Select * from FeedLibrary where category='Grass / Legume'", Connection);
DataTable Dtable = new DataTable();
DataA.Fill(Dtable);
frm2.FeedSelectListBox .DataSource = Dtable;

DataTable as DataSource in ReportViewer

(First of all I'm so sorry about my english, because I'm a stranger and I don't know well)
I'm working in a school project. But I need to set a DataTable as DataSource in ReportViewer. First the user type the ID of the Document, and click on the button, the button calls an class that do a select in my database and return 12 fields. I've created a DataSet with all fields that the select results and I've selected it as the Report DataSource. But I need to transfer the data of the select to the DataSet, because when I start my application the Report has an error. Here is the code, and I hope you can help me! Thanks.
Buttton Code:
SelectDocumento doc = new SelectDocumento();
doc.ImprimirDoc(int.Parse(txtID.Text));
Class that select data in my database:
public void ImprimirDoc(int id)
{
string pesquisar = "CALL SP_Imprimir_Documento(" + id + ")";
MySqlConnection con;
con = new MySqlConnection("Persist Security Info=false; server=localhost; database=hospital; uid=root; pwd=");
MySqlDataAdapter adapter = new MySqlDataAdapter(pesquisar, con);
DataTable dt = new DataTable();
dt.TableName = "DataSet1";
con.Open();
adapter.Fill(dt);
ImprimirDocumento imprimir = new ImprimirDocumento(dt);
imprimir.ShowDialog();
}
Code of the Report Form:
private DataTable proc;
public ImprimirDocumento(DataTable select)
{
InitializeComponent();
proc = select;
}
ConexaoHospital bd = new ConexaoHospital();
SelectDocumento doc = new SelectDocumento();
private void ImprimirDocumento_Load(object sender, EventArgs e)
{
this.rptDocumento.RefreshReport();
this.rptDocumento.LocalReport.DataSources.Clear();
Microsoft.Reporting.WinForms.ReportDataSource rprtDTSource = new Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", proc);
this.rptDocumento.LocalReport.DataSources.Add(rprtDTSource);
this.rptDocumento.RefreshReport();
}
Error that the Report Displays:
Error
If someone have a simmilar problem this way of my post is correct and my problem was because my ReportViewer DataSet name was different than my DataTable. My DataTable name was "DataSet1" and my DataSet name was "Documento". I changed the DataSet name for "DataSet1" and it works.

Issue with bindingsource refresh after row insert - Object reference not set to an instance of an object

Windows Form Application,
VS 2010 C#,
Access 2003
I am referencing from this website, here. My aim is to show updated records (insert/delete update) without closing and restarting the application to show new reflection. I have quite a few textboxes, comboxes etc, so I am not using datagridview.
From that website there are two pieces of code...
bindingNavigator1.BindingSource = bdSource;
this.dataGridView1.DataSource = bdSource;
So I did this...
this.table1BindingSource = dbSource;
and gave a error of "Object reference not set to an instance of an object." With a warning that dbSource is never assigned and will aways have a default value null.
my insert command parameter structure..
OleDbCommand cmd = new OleDbCommand(#"INSERT INTO Table1 (ID, Name) VALUES(#ID, #Name)", myCon);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#ID", txtID.Text);
cmd.Parameters.AddWithValue("#Name", txtName.Text);
myCon.Open();
cmd.ExecuteNonQuery();
myCon.Close();
The following method I am hoping data would be refreshed...
private void btnReload_Click(object sender, EventArgs e)
{
OleDbDataAdapter.Update(dtSource);
}
and...
public partial class Form1 : Form
{
private OleDbConnection myCon;
private string connectionString;
private string commandText;
private OleDbCommandBuilder OleDbCommandBuilder;
private OleDbDataAdapter OleDbDataAdapter;
private DataTable dtSource;
private BindingSource dbSource;
public Form1()
{
connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data.. ";
commandText = "SELECT * FROM TABLE1";
myCon = new OleDbConnection(connectionString);
OleDbDataAdapter = new OleDbDataAdapter(commandText, myCon);
OleDbCommandBuilder = new OleDbCommandBuilder(OleDbDataAdapter);
dtSource = new DataTable();
OleDbDataAdapter.Fill(dtSource);
dbSource = new BindingSource();
dbSource.DataSource = dtSource;
Thanks in advance for anyone who could help me
EDIT
I also have navigation buttons..
private void fnDisplayPosition()
{
this.label2.Text = this.table1BindingSource.Position + 1 + " of " +
this.table1BindingSource.Count;
table1BindingSource.ResetBindings(false);
}
then in the Form load...
private void Form1_Load(object sender, EventArgs e)
{
this.fnDisplayPosition();
}
Example of navigation button...
private void btnFirst_Click(object sender, EventArgs e)
{
this.table1BindingSource.MoveFirst();
this.fnDisplayPosition();
}
UPDATE 2
I did some error in coding so warning signs and errors are gone
As I understand, here you initalize bindingSource called bdSource
bdSource = new BindingSource();
But then you try to set the dataSource
dbSource.DataSource = dtSource;
for bindingSource called dbSource.You haven't initalized it yet. So, which one of them you are going to use?
Also, what is table1BindingSource in your code?
The issue was with tableadapters and bindingsource tied to texboxes and others alike. I have explained it here in full.

Combobox databinding showing system.data.datarowview

I am binding combobox with datasource, displaymember, valuemember. It is working fine in my computer but it is not working in clients pc. Following is my source code:
cbxAlloyBinding method is called from the Constructor of the UserControl.
private void cbxAlloyBinding()
{
DataTable dt = new DataTable();
SqlDataAdapter adp = new SqlDataAdapter("SELECT alloyName,alloyId FROM alloy", con);
adp.Fill(dt);
if (dt.Rows.Count > 0)
{
cbxMetal.DisplayMember = "alloyName";
cbxMetal.ValueMember = "alloyId";
cbxMetal.DataSource = dt;
}
else
{
cbxMetal.Text = "";
}
}
private void cbxMetal_SelectedIndexChanged(object sender, EventArgs e)
{
if (cbxMetal.SelectedIndex != -1)
{
DataTable dt = new DataTable();
tempcmd = new SqlCommand("SELECT specification,alloyCode FROM alloy where alloyId='" + cbxMetal.SelectedValue + "'", con);
SqlDataAdapter adp = new SqlDataAdapter(tempcmd);
adp.Fill(dt);
if (dt.Rows.Count > 0)
{
txtSpecification.Text = dt.Rows[0]["alloyCode"].ToString();
txtSupplyConditions.Text = dt.Rows[0]["specification"].ToString();
cbxheatBinding();
}
else
{
txtSpecification.Text = "";
}
}
}
This is bothering me from last two days and i almost tried all tricks but it is still not working.
Client's PC is using Windows 7 ultimate, sql server 2005 and .net framework 3.5.
This definitely happens if your cbxMetal_SelectedIndexChanged is called before cbxAlloyBinding() is called in your constructor.
For instance (see the code below), you may have other combobox bindings in constructor which may come before cbxAlloyBinding() in constructor, and those bindings are calling cbxMetal_SelectedIndexChanged.
public Constructor()
{
InitializeComponent();
cbxheatBinding(); //1st Three Binding Methods may be somehow related to your cbxMetal,
dtpStartDateBinding(); //which leads them to call cbxMetal_SelectedIndexChanged method.
dtpEndDateBinding();
cbxAlloyBinding();
}
What I suspect is your cbxMetal.DataSource is set from some other point in your code and well before DisplayMember and ValueMember are assigned;
Just remember, System.DataRow.DataRowView will occur only if
ComboBox.SelectedValue is called before ValueMember assignment.
setting the DisplayMember and ValueMemeber after setting the DataSource fixed this issue for me.
cbxMetal.DataSource = dt;
cbxMetal.DisplayMember = "alloyName";
cbxMetal.ValueMember = "alloyId";
It seems problem is not with the code you pasted here, it may be with client environment, connection, privileges etc. You must give more info about that 'it is not working in clients pc'. What systems they use, what is the error, have you tried debugging in client side?
*Edit:*then you have to find the problem tracing all the operation from the beginning. My advice is that make a dummy windows form application, just a standard form, a combobox and a button. ON the click event of button just do what you did. JUst bind the combo and send this temp app to the client. If it works then do step by step.Ex:
private void button1_Click(object sender, EventArgs e)
{
string conStr = "Data Source=PC-303\\SQLEXPRESS;Initial Catalog=sokaklar;User ID=sa;Password=*****";
SqlDataAdapter adapter = new SqlDataAdapter("SELECT DISTINCT IL, IL_ID FROM sokaklar ORDER BY IL", new SqlConnection(conStr));
DataTable dt = new System.Data.DataTable();
adapter.Fill(dt);
comboBox1.DisplayMember = "IL";
comboBox1.ValueMember = "IL_ID";
comboBox1.DataSource = dt;
}
I created this app in one minute, and it is working for me.
I resolved same this:
/*First get DataSource*/
comboBox1.DataSource = dt;
/*Then determine DisplayMember y ValueMember*/
comboBox1.DisplayMember = "YOUR_FIELD_NAME";
comboBox1.ValueMember = "YOUR_OTHER_FIELD_NAME";
This only works with
System.Data.DataTable
or
List
data sources
It was showing me the same exception, so I did this and it worked
private void cb_category_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable mydt = new DataTable();
try
{
mydt = request.GetItem(int.Parse(cb_category.SelectedValue.ToString()));
}
catch { }
if(mydt.Rows.Count>0)
{
cb_Item.DataSource = mydt;
cb_Item.DisplayMember = "dispmember";
cb_Item.ValueMember = "valmember";
}
else
{
cb_Item.DataSource = null;
}
}
THIS WILL DEFINITELY HELP TO YOU
on the load Event you want to Just Write this code
onformload()
{
cmb_dept.Items.Clear();
SqlConnection conn = new SqlConnection(#"DATA SOURCE=(localdb)\MSSQLLocalDB;INTEGRATED SECURITY=true;INITIAL CATALOG=EMPLOYEE;");
conn.Open();
SqlCommand command = new SqlCommand("select dept_id, dept_name from department", conn);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataSet ds = new DataSet();
adapter.Fill(ds);
cmb_dept.ValueMember = "dept_id";
cmb_dept.DisplayMember = "dept_name";
cmb_dept.DataSource = ds.Tables[0];
}
try using Use the code where you want to access the values........
string dept = cmb_dept.Text;
MessageBox.Show("val=" + dept);
YOUR combobox.text = System.Data.DataRowView Will be Solved ##
reading the answer in this post tells me there are so many ways this bug can reveal itself, for me it was the following: I had the combobox bound exact like mentioned in the question, and it was working fine, I change the Sorted property of the combobox to True in the Designer and started getting datarowview thing in each item. After wasting a lot of time found out that Sorted property should be False for this to work as expected. Sorting has to be dont through the query you used to get the data.
"comboBox1.SelectedValue" returns object and you want as string so convert it Convert.ToString(comboBox1.SelectedValue) and then use
for example:
tempcmd = new SqlCommand("SELECT specification,alloyCode FROM alloy where alloyId='" + Convert.ToString(cbxMetal.SelectedValue) + "'", con);

Categories

Resources