Unable to update SQL Server database with value from textbox in gridview - sql-server

I have just joined stackoverflow as a relatively novice user of visual studio, with the hope that someone might be able to help answer a question to a problem I'm having.
I'm sure it's quite simple, but at the moment I have a Gridview which is bound to a table from our SQL Server.
My issue I'm having is with the gridview, which was generated with the help of the in-built wizard. My update SQL statement is a custom one, which is quite simply:
UPDATE SMCsummove
SET SubmitQty = #Textbox1 * - 1, HasBeenEdited = 'Y'
WHERE (SMCPOinteger = #SMCPOinteger) AND (SMCproduct = #PartNo)
Now being a novice, I am not quite sure if I am doing this right, but #Textbox1 is the value that the user enters as a new value to update the table with, after they have clicked the autogenerated 'edit' button. Quite simply once they have clicked the 'update' button, the gridview reverts back to the original value that was there in the SubmitQty column.
If anyone can shed some light or point out any massive oversights, that would be most appreciated!

Need to see more of the code from the gridview to know for sure, but it looks like a postback is occurring and this is causing your gridview to bind again and be reset.
I'm pretty new to this as well and what I have found works for gridviews is to have a pageload event like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bindGridView();
}
}
Then have a separate statement for the binding (this is one that I uses:
private void bindGridView()
{
string connectionString = WebConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
string selectSQL = String.Format("SQL Statement here");
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(selectSQL, con);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "Review");
GridView1.DataSource = ds;
GridView1.DataBind();
}
You may find you have to call the gridbind as well after updating records to repopulate the gridview with the updated values.

Related

Unexpected behaviour with DataGridViewComboBoxColumn Value/Display members binded to DataTable from an Access DB

I'm doing something to be supposedly straight and simple, yet I cannot make it work. I've an Access DB (64 bits), which is accessed by an OleDB connection. If I bind the values of a DataGridViewComboBoxColumn to a DataTable's fields ([int]id and [string]name), the ComboBoxes are rendered correctly (it displays the "DisplayMember", and keeps the "ValueMember" as an internal value). Yet, as soon as I set the target field for storing it's value with "DataPropertyName", the ComboBox now renders the "ValueMember" - or rather the "DataPropertyName" takes priority [??] - (see the attached images).
The code used is shown in the following snipet:
private OleDbDataAdapter empleadosDA_local = new OleDbDataAdapter();
private OleDbDataAdapter activosDA_local = new OleDbDataAdapter();
private DBLocal dbConn_local;
internal DataSet catalogosDS, auxsDS;
internal BindingSource activosBind = new BindingSource();
......
private void BindControls() {
DataGridViewComboBoxColumn activos_responsable1DGComboBox;
activosBind.DataMember = "Activos";
activosBind.DataSource = catalogosDS;
this.Activos_dataGrid.AutoGenerateColumns = false;
// Create DGComboBox
activos_responsable1DGComboBox = new DataGridViewComboBoxColumn();
activos_responsable1DGComboBox.ValueMember = "id_empleado";
activos_responsable1DGComboBox.DisplayMember = "nombre";
activos_responsable1DGComboBox.DataSource = auxsDS.Tables["Responsables1"];
activos_responsable1DGComboBox.HeaderText = "Responsable1:";
// activos_responsable1DGComboBox.DataPropertyName = "idEmpleado1"; <--- this is the line that creates the unexpected behaviour
this.Activos_dataGrid.Columns.Insert(6, activos_responsable1DGComboBox);
this.Activos_dataGrid.Columns[6].Name = "Activos_dgResponsable1";
this.Activos_dataGrid.Columns["Activos_dgResponsable1"].Width = 195;
this.Activos_dataGrid.Columns["Activos_dgResponsable1"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
this.Activos_dataGrid.DataSource = activosBind;
I've done this in other Forms and it works fine using this same logic, but I just cannot find the reason why this fails. Any help will be greatly appreciated.
EDIT:
JohnG asked for the schemas that feeds the DataSource of the ComboBox and the target table where it's stored, so we can identify any data type inconsistencies:
ComboBox DataSource:
TargetTable which feeds the DataGridView:
So it results that the ComboBox's source table has an autoincrement field (the primary key), and this is forcibly a "number long integer", and I was using for storing it a table with a field defined as integer. Setting the target field to long int solved the issue.

Populating a Combo Box

I created a Windows Form, with a ComboBox, and a Local Database in Visual Studio 2010. The database has a table with a column whose rows I want to list in the combo box. How can I achieve this?
I tried adding a data source with the column I am interested in through the IDE, but it did not work.
I created a Windows Forms Application with a Windows Form containing a ComboBox.
I created a Local Database containing a Table with a single column and three test rows.
I added a data source containing the column I am interested in.
Finally, I bound the combo box to the data source, but the result is strange.
This is the raw code to accomplish what you are asking:
string strCmd = "";
string strConn = "";
SqlConnection sqlConn = new SqlConnection();
SqlCommand sqlCmd = new SqlCommand(strCmd, sqlConn);
SqlDataReader sqlRdr = new SqlDataReader();
sqlConn.Open();
if (comboBox1.Items.Count > 0)
comboBox1.Items.Clear();
sqlRdr = sqlCmd.ExecuteReader();
while (sqlRdr.Read())
comboBox1.Items.Add(sqlRdr[0].ToString());
sqlRdr.Close();
sqlConn.Close();
There are a few things you will need to wire-up first though. The first one is this:
string strCmd = ""; // Insert your SQL statement here.
Second:
string strConn = ""; // Your db connection string goes here.
Thirdly:
if (comboBox1.Items.Count > 0) // You don't have to use this. It just checks to see
comboBox1.Items.Clear(); // if there is anything in the combobox and clears it.
Lastly, since you are making something that handles interactions between your form and a database, I strongly suggest that you use SqlParameters to prevent SQL Injection attacks.

Listbox won't display updated database info once program is published

I am a beginner to programming and I am trying to make a program that tracks my jogging data in WPF. I set up a listbox that has databinding with my compact sql database where my info gets logged to. While I am in visual studio it works as it should, but when I publish the program, the listbox will no longer display the proper info from the database. It starts fresh all over again each time I start a new session of the program. I know that the info is in the database because I have charts that will properly show all the latest logged data. The listbox, however, will only show data logged during that current session. When I close down the program and reopen, the data from my previous session is not displayed in the listbox anymore.
My code looks like this:
runDataDataSet1 ds;
runDataDataSet1TableAdapters.runDataTableTableAdapter dt;
weightDataSet wds;
weightDataSetTableAdapters.weightTableTableAdapter wdt;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ds = ((runDataDataSet1)(this.FindResource("runDataDataSet1")));
dt = new runDataDataSet1TableAdapters.runDataTableTableAdapter();
dt.Fill(ds.runDataTable);
CollectionViewSource cvs = ((CollectionViewSource)(this.FindResource("runDataTableViewSource")));
cvs.View.MoveCurrentToFirst();
wds = ((weightDataSet)(this.FindResource("weightDataSet")));
wdt = new weightDataSetTableAdapters.weightTableTableAdapter();
wdt.Fill(wds.weightTable);
CollectionViewSource wcvs = ((CollectionViewSource)(this.FindResource("weightTableViewSource")));
wcvs.View.MoveCurrentToFirst();
To submit the data I have this code for when the submit button is pushed:
double pace = runData.runPace(runData.milesRun, runData.timeRun);
double pace2 = Math.Round(pace, 1);
double milesDuration = Math.Round((runData.mileDuration(runData.milesRun, runData.timeRun)), 1);
paceTextBox.Text = ((milesDuration) + " min mile");
//UPDATE DATABASE
string myConnectionString = #"Data Source=C:\Users\zfam\My Projects\programming\visual studio\XTrakker\XTrakker\runData.sdf";
string mySelectQuery = "SELECT [int], [runDate], [runDist], [runTime], [runPace] FROM [runDataTable] order by [int] desc";
DataRow dr = ds.Tables["runDataTable"].NewRow();
SqlCeDataAdapter adapter = new SqlCeDataAdapter(mySelectQuery, myConnectionString);
dr["runDate"] = date;
dr["runDist"] = distData;
dr["runTime"] = timeData;
dr["runPace"] = milesDuration;
ds.Tables["runDataTable"].Rows.Add(dr);
SqlCeCommandBuilder projectBuilder = new SqlCeCommandBuilder(adapter);
DataSet newSet = ds.GetChanges(DataRowState.Added);
adapter.Update(newSet, "runDataTable");
adapter.Dispose();
Again, while I am in visual studio and I run the program, this all works as it should. Once I publish, the listbox will only show the data from the current session, even the the actual database file is being updated. Perhaps I am doing this all wrong? Any thoughts?
Hard to say, but I am a bit confused about this line:
string myConnectionString = #"Data Source=C:\Users\zfam\My Projects\programming\visual studio\XTrakker\XTrakker\runData.sdf";
Look like you hardcode your datasource provider. Are you sure you use the same datasource in visual studio, and when you publish your app?
Maybe the datasource is re-created at each execution, which could explain why you have always new data.

Will a Winforms grid keep its datasource in memory? .Net

I've a grid in my winforms application and i bind a huge dataset to the grid. Will the dataset be stored in the memory by the grid after calling DataBind(). How does it operate on the data binded to the grid?
Update
I wrote the following code
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection("Server=server;Initial Catalog=db;User ID=testv;Pwd=pass"))
{
con.Open();
using (SqlCommand com = new SqlCommand("select * from tbl_Sample", con))
{
using (SqlDataAdapter ada = new SqlDataAdapter(com))
{
ada.Fill(dt);
dgvMain.DataSource = dt;
dt.Dispose();
}
}
}
After assigning the datatable as the datasource i'm able to dispose it. So does it make a copy in the memory?
Thanks
NLV
It doesn't make a copy, it makes a reference to the original datasource object.
P.S. Making a huge dataset is not a good idea anyway. If you need to display lots of rows, make some kind of paging or filters and restrict number of rows to load and display.

Refreshing BindingSource after insert (Linq To SQL)

I have a grid bound to a BindingSource which is bound to DataContext table, like this:
myBindingSource.DataSource = myDataContext.MyTable;
myGrid.DataSource = myBindingSource;
I couldn't refresh BindingSource after insert. This didn't work:
myDataContext.Refresh(RefreshMode.OverwriteCurrentValues, myBindingSource);
myBindingSource.ResetBinding(false);
Neither this:
myDataContext.Refresh(RefreshMode.OverwriteCurrentValues, myDataContext.MyTable);
myBindingSource.ResetBinding(false);
What should I do?
I have solved the problem but not in a way I wanted.
Turns out that DataContext and Linq To SQL is best for unit-of-work operations. Means you create a DataContext, get your job done, discard it. If you need another operation, create another one.
For this problem only thing I had to do was recreate my DataContext like this.dx = new MyDataContext();. If you don't do this you always get stale/cached data. From what I've read from various blog/forum posts that DataContext is lightweight and doing this A-OK. This was the only way I've found after searching for a day.
And finally one more working solution.
This solution works fine and do not require recreating DataContext.
You need to reset internal Table cache.
for this you need change private property cachedList of Table using reflection.
You can use following utility code:
public static class LinqDataTableExtension
{
public static void ResetTableCache(this ITable table)
{
table.InternalSetNonPublicFieldValue("cachedList", null);
}
public static void ResetTableCache(this IListSource source)
{
source.InternalSetNonPublicFieldValue("cachedList", null);
}
public static void InternalSetNonPublicFieldValue(this object entity, string propertyName, object value)
{
if (entity == null)
throw new ArgumentNullException("entity");
if(string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException("propertyName");
var type = entity.GetType();
var prop = type.GetField(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
if (prop != null)
prop.SetValue(entity, value);
// add any exception code here if property was not found :)
}
}
using something like:
var dSource = Db.GetTable(...)
dSource.ResetTableCache();
You need to reset your BindingSource using something like:
_BindingSource.DataSource = new List();
_BindingSource.DataSource = dSource;
// hack - refresh binding list
Enjoy :)
Grid Data Source Referesh by new query instead just Contest.Table.
Simple Solution < But Working.
Whre is eg.
!!!!! Thanks - Problem Solved after no of days !!! but with so simple way ..
CrmDemoContext.CrmDemoDataContext Context = new CrmDemoContext.CrmDemoDataContext();
var query = from it in Context.Companies select it;
// initial connection
dataGridView1.DataSource = query;
after changes or add in data
Context.SubmitChanges();
//call here again
dataGridView1.DataSource = query;
I have the same problem. I was using a form to create rows in my table without saving the context each time. Luckily I had multiple forms doing this and one updated the grid properly and one didn't.
The only difference?
I bound one to the entity similarly (not using the bindingSource) to what you did:
myGrid.DataSource = myDataContext.MyTable;
The second I bound:
myGrid.DataSource = myDataContext.MyTable.ToList();
The second way worked.
I think you should also refresh/update datagrid. You need to force redraw of grid.
Not sure how you insert rows. I had same problem when used DataContext.InsertOnSubmit(row), but when I just inserted rows into BindingSource instead BindingSource.Insert(Bindingsource.Count, row)
and used DataContext only to DataContext.SubmitChanges() and DataContext.GetChangeSet(). BindingSource inserts rows into both grid and context.
the answer from Atomosk helped me to solve a similar problem -
thanks a lot Atomosk!
I updated my database by the following two lines of code, but the DataGridView did not show the changes (it did not add a new row):
this.dataContext.MyTable.InsertOnSubmit(newDataset);
this.dataContext.SubmitChanges();
Where this.dataContext.MyTable was set to the DataSource property of a BindingSource object, which was set to the DataSource property of a DataGridView object.
In code it does looks like this:
DataGridView dgv = new DataGridView();
BindingSource bs = new BindingSource();
bs.DataSource = this.dataContext.MyTable; // Table<T> object type
dgv.DataSource = bs;
Setting bs.DataSource equals null and after that back to this.dataContext.MyTable did not help to update the DataGridView either.
The only way to update the DataGridView with the new entry was a complete different approach by adding it to the BindingSource instead of the corresponding table of the DataContext, as Atomosk mentioned.
this.bs.Add(newDataset);
this.dataContext.SubmitChanges();
Without doing so bs.Count; returned a smaller number as this.dataContext.MyTable.Count();
This does not make sense and seems to be a bug in the binding model in my opinion.

Resources