The current situation is that there is a databound data grid view that many people need to make changes to on a daily basis simultaneously. The grid has to be able to save and update but it is not working correctly since it is very active.
Here’s the scenario:
- 3 people open the grid form at the same time.
- They make changes to 3 different rows of data.
- Person 1 saves changes and is successful.
- Person 2 Saves changes and is successful but person 1’s changes are now gone since person 2’s grid was not synced with the data that person 1 just submitted.
- Person 3 saves changes and wipes out anything that person 1 and 2 did because person 3’s data grid view was not synced up with the updated data.
I have tried this approach first:
private MySqlDataAdapter da;
private MySqlConnection conn;
BindingSource bs = new BindingSource();
DataSet ds = null;
string qry;
string ConnString = System.Configuration.ConfigurationManager.AppSettings["ConnectionString"];
// THE LOAD METHOD
private void LoadDataToGrid(string srcTable, string query)
{
conn = new MySqlConnection(ConnString);
// ADD ANY QUERY
qry = query;
da = new MySqlDataAdapter(qry, conn);
conn.Open();
ds = new DataSet();
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
// USE TABLE NAME
da.Fill(ds, srcTable);
//USE TABLE NAME
bs.DataSource = ds.Tables[srcTable];
dataGridView1.DataSource = bs;
// CUSTOMIZE GRID
txtRows.Text = dataGridView1.Rows.Count.ToString();
dataGridView1.AutoResizeColumns();
dataGridView1.AllowUserToDeleteRows = false;
}
// THE SAVE METHOD
private void SaveDataFromGrid(string srcTable)
{
// USE TABLE NAME
DataTable dt = ds.Tables[srcTable];
this.dataGridView1.BindingContext[dt].EndCurrentEdit();
this.da.Update(dt);
txtRows.Text = dataGridView1.Rows.Count.ToString();
}
This did not work out for me because of the reasoning above. Data just wasen’t getting saved correctly.
Here was my second thought, but still suffers from above issue:
// Load event
dataGridView1.DataSource = context.TableName;
// btnSave_click Event
connection.open();
// loop through cells in current row and apply changes by id
context.tableName.Attach(DataFromGrid);
context.ObjectStateManager.ChangeObjectState(DataFromGrid, System.Data.EntityState.Modified);
context.savechanges();
Basically, how can I solve this disconnection problem? Has anyone had this issue before?
This issue is probably more complicated than one code snippet is going to solve. It seems like you have a couple of things to resolve first, before you get into the implementation;
Firstly; does each person’s changes actually have to commit an entire grid? According to your scenario, each person changes a different row of data. Modifying your code to commit changes to just the row that was modified will cut down your conflict scenarios considerably.
Secondly, and regardless of whether the conflicts are occurring in one row or many, you need to decide how to manage conflicts (you’ve not noted what you expect to happen – e.g; database wins, user’s choice, ett.).
EF implements an optimistic concurrency mode (no database locks), however by default it will just elect to overwrite database changes when you commit your local changes. You need to modify your EF configuration to set ConcurrenyMode=Fixed so that it will not automatically overwrite changes when you have not ‘gotten latest’ before committing rows.
See here for a bit more info on how EF handles concurrency: http://msdn.microsoft.com/en-us/library/bb738618.aspx
Once you’ve modified the EF config, you’ll start getting exceptions when conflicts are detected, which you’ll need to handle, by refreshing the data either in the database (with local changes) or refreshing the local data (with database changes).