SQLCeResultSet does not update first row

A

aknittel

Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the loop
out and just updated row 1, it will not be reflected in the grid. This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the updates
to SQLCE will occur asychronously in another class. The whole point in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder = Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder + "\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

When you move to a new row in the DataGrid, the grid calls EndEdit which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.
 
A

aknittel

Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works fine
with the Datagrid bound to a table in a dataset.

When you move to a new row in the DataGrid, the grid calls EndEdit which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the loop
out and just updated row 1, it will not be reflected in the grid. This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the updates
to SQLCE will occur asychronously in another class. The whole point in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder = Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder + "\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works fine
with the Datagrid bound to a table in a dataset.

When you move to a new row in the DataGrid, the grid calls EndEdit which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the loop
out and just updated row 1, it will not be reflected in the grid. This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the updates
to SQLCE will occur asychronously in another class. The whole point in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder = Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder + "\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

OK, with more observations looks like rows 11-20 are the NON-VISIBLE
ROWS in the datagrid. What is the purpose of
ResultSetOptions.Sensitive id only the NON-VISIBLE rows are being
retrieved dynamically from the database???

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works fine
with the Datagrid bound to a table in a dataset.

When you move to a new row in the DataGrid, the grid calls EndEdit which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the loop
out and just updated row 1, it will not be reflected in the grid. This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the updates
to SQLCE will occur asychronously in another class. The whole point in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder = Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder + "\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Graham McKechnie

Are you sure i in your loop matches your product id. Have you stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works fine
with the Datagrid bound to a table in a dataset.

When you move to a new row in the DataGrid, the grid calls EndEdit
which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the
loop
out and just updated row 1, it will not be reflected in the grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the
updates
to SQLCE will occur asychronously in another class. The whole point
in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder +
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and reading
it directly with VS 2005.


Graham said:
Are you sure i in your loop matches your product id. Have you stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls EndEdit
which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the
loop
out and just updated row 1, it will not be reflected in the grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the
updates
to SQLCE will occur asychronously in another class. The whole point
in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder +
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the same
way it does when it is bound to a DataSet and you update a row in the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and reading
it directly with VS 2005.


Graham said:
Are you sure i in your loop matches your product id. Have you stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls EndEdit
which
calls Update. If you want to update only a single row, you need to call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is not
updated in the bound datagrid? When I inspect the database, ALL rows
(ProductID 1 to 20) have been updated as expected. If I take the
loop
out and just updated row 1, it will not be reflected in the grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the
updates
to SQLCE will occur asychronously in another class. The whole point
in

binding and using ResultSetOptions.Sensitive was that any changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder +
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY [Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

Yes, this is what I meant although I didn't realize you weren't updating the
result set in the grid, but it's still the same principle. The result set is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get new
data until you move around in it.

As for what to do about this, one approach is to periodically have the grid
refresh itself from the data on a timer. The other approach would be to have
the operation that makes the changes raise an event that ultimately causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to refresh
itself from the DataSet, the DataSet would still have the old data in it.
The other difference with a DataSet is that you can add rows to a DataSet
bound to a grid and that works the way you expect, but you shouldn't use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the same
way it does when it is bound to a DataSet and you update a row in the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and reading
it directly with VS 2005.


Graham said:
Are you sure i in your loop matches your product id. Have you stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the
data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically
as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls EndEdit
which
calls Update. If you want to update only a single row, you need to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is
not
updated in the bound datagrid? When I inspect the database, ALL
rows
(ProductID 1 to 20) have been updated as expected. If I take
the
loop
out and just updated row 1, it will not be reflected in the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the
updates
to SQLCE will occur asychronously in another class. The whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

Ahh, OK. I began to realize this last night. However, mere scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row to
see the row change.

My old DataSet model does raise events to update the row in the bound
DataSet when it updates the underlying database, so I can I could adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or is
there some finer-grained row-relative mechanism to accomplish the same
thing? The effect I am trying to achieve is the same one I get updating
the DataSet for a bound datagrid. That is, if the user is viewing the
rows with the one that changes, they see an update. If not, when they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing mechanism.
Is this true?

Yes, this is what I meant although I didn't realize you weren't updating the
result set in the grid, but it's still the same principle. The result set is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get new
data until you move around in it.

As for what to do about this, one approach is to periodically have the grid
refresh itself from the data on a timer. The other approach would be to have
the operation that makes the changes raise an event that ultimately causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to refresh
itself from the DataSet, the DataSet would still have the old data in it.
The other difference with a DataSet is that you can add rows to a DataSet
bound to a grid and that works the way you expect, but you shouldn't use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the same
way it does when it is bound to a DataSet and you update a row in the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other object
(like CurrencyManager) to update the Datagrid, I am updating the
data
source (the first 20 rows in the database with the usual SQL Update
statement).

I am expecting to see the datagrid update all 20 rows automatically
as
a result of that because it is using ResultSetOptions.Sensitive. It
shows rows 2-20 are updated with "XXX", but not row 1. This works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls EndEdit
which
calls Update. If you want to update only a single row, you need to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set is
not
updated in the bound datagrid? When I inspect the database, ALL
rows
(ProductID 1 to 20) have been updated as expected. If I take
the
loop
out and just updated row 1, it will not be reflected in the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as the
updates
to SQLCE will occur asychronously in another class. The whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" + DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

As far as I've been able to figure out, ExecuteResultSet is exactly what you
want. Once you get the new result set from doing that, then when you bind
that new result set to the grid, you'll see the new data, and the whole
operation should be pretty fast. You can use the old SqlCeConnection object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time. Make sure
you close the old result set (which calls Dispose internally) before issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row to
see the row change.

My old DataSet model does raise events to update the row in the bound
DataSet when it updates the underlying database, so I can I could adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or is
there some finer-grained row-relative mechanism to accomplish the same
thing? The effect I am trying to achieve is the same one I get updating
the DataSet for a bound datagrid. That is, if the user is viewing the
rows with the one that changes, they see an update. If not, when they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing mechanism.
Is this true?

Yes, this is what I meant although I didn't realize you weren't updating
the
result set in the grid, but it's still the same principle. The result set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get new
data until you move around in it.

As for what to do about this, one approach is to periodically have the
grid
refresh itself from the data on a timer. The other approach would be to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data in it.
The other difference with a DataSet is that you can add rows to a DataSet
bound to a grid and that works the way you expect, but you shouldn't use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the same
way it does when it is bound to a DataSet and you update a row in the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other
object
(like CurrencyManager) to update the Datagrid, I am updating the
data
source (the first 20 rows in the database with the usual SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls
EndEdit
which
calls Update. If you want to update only a single row, you need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set
is
not
updated in the bound datagrid? When I inspect the database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If I take
the
loop
out and just updated row 1, it will not be reflected in the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as
the
updates
to SQLCE will occur asychronously in another class. The
whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

One observation here is that when I did close the resultset, the
datagrid refreshed its view with "X's". I would assume (and will try
tonight), that if I close and then immediately re-issue the
ExecuteResultSet, there will be some undesirable flashing. If so, how
can I prevent such flashing? That's why I asked if there was a more
finer-grained row relative way of coaxing the datagrid to display the
changes only to that row.

However, what I think you are saying here is that if I want to buy into
the use of SqlCeResultSet, I have realize that what it is doing behind
the scenes is entirely dependent on re-issuing a DataReader query on
the underlying source, so that's what I have to do.
As far as I've been able to figure out, ExecuteResultSet is exactly what you
want. Once you get the new result set from doing that, then when you bind
that new result set to the grid, you'll see the new data, and the whole
operation should be pretty fast. You can use the old SqlCeConnection object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time. Make sure
you close the old result set (which calls Dispose internally) before issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row to
see the row change.

My old DataSet model does raise events to update the row in the bound
DataSet when it updates the underlying database, so I can I could adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or is
there some finer-grained row-relative mechanism to accomplish the same
thing? The effect I am trying to achieve is the same one I get updating
the DataSet for a bound datagrid. That is, if the user is viewing the
rows with the one that changes, they see an update. If not, when they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing mechanism.
Is this true?

Yes, this is what I meant although I didn't realize you weren't updating
the
result set in the grid, but it's still the same principle. The result set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get new
data until you move around in it.

As for what to do about this, one approach is to periodically have the
grid
refresh itself from the data on a timer. The other approach would be to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data in it.
The other difference with a DataSet is that you can add rows to a DataSet
bound to a grid and that works the way you expect, but you shouldn't use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the same
way it does when it is bound to a DataSet and you update a row in the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other
object
(like CurrencyManager) to update the Datagrid, I am updating the
data
source (the first 20 rows in the database with the usual SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls
EndEdit
which
calls Update. If you want to update only a single row, you need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set
is
not
updated in the bound datagrid? When I inspect the database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If I take
the
loop
out and just updated row 1, it will not be reflected in the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as
the
updates
to SQLCE will occur asychronously in another class. The
whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

I haven't noticed any flashing when I do this, but if you do when you get a
chance to try it, please let me know.

Although SqlCeResultSet is a DataReader and inherits from SqlCeDataReader,
reissuing that ExecuteResultSet query should be quite fast since you don't
need to iterate though all the records that match the query. The DataGrid
control (when you bind it to the new result set) will only fetch the data
for the visible rows, so that should also be pretty fast.

Let me know how this works out for you,

--
Ginny Caughey
Device Application Development MVP


One observation here is that when I did close the resultset, the
datagrid refreshed its view with "X's". I would assume (and will try
tonight), that if I close and then immediately re-issue the
ExecuteResultSet, there will be some undesirable flashing. If so, how
can I prevent such flashing? That's why I asked if there was a more
finer-grained row relative way of coaxing the datagrid to display the
changes only to that row.

However, what I think you are saying here is that if I want to buy into
the use of SqlCeResultSet, I have realize that what it is doing behind
the scenes is entirely dependent on re-issuing a DataReader query on
the underlying source, so that's what I have to do.
As far as I've been able to figure out, ExecuteResultSet is exactly what
you
want. Once you get the new result set from doing that, then when you bind
that new result set to the grid, you'll see the new data, and the whole
operation should be pretty fast. You can use the old SqlCeConnection
object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time. Make
sure
you close the old result set (which calls Dispose internally) before
issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row to
see the row change.

My old DataSet model does raise events to update the row in the bound
DataSet when it updates the underlying database, so I can I could adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or is
there some finer-grained row-relative mechanism to accomplish the same
thing? The effect I am trying to achieve is the same one I get updating
the DataSet for a bound datagrid. That is, if the user is viewing the
rows with the one that changes, they see an update. If not, when they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing mechanism.
Is this true?


Ginny Caughey [MVP] wrote:
Yes, this is what I meant although I didn't realize you weren't
updating
the
result set in the grid, but it's still the same principle. The result
set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get
new
data until you move around in it.

As for what to do about this, one approach is to periodically have the
grid
refresh itself from the data on a timer. The other approach would be
to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data in
it.
The other difference with a DataSet is that you can add rows to a
DataSet
bound to a grid and that works the way you expect, but you shouldn't
use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the
same
way it does when it is bound to a DataSet and you update a row in
the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in
the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor,
create a
button for it, and put the code in the button's click event,
only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other
object
(like CurrencyManager) to update the Datagrid, I am updating
the
data
source (the first 20 rows in the database with the usual SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using
ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This
works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls
EndEdit
which
calls Update. If you want to update only a single row, you
need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result
set
is
not
updated in the bound datagrid? When I inspect the
database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If I
take
the
loop
out and just updated row 1, it will not be reflected in
the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as
the
updates
to SQLCE will occur asychronously in another class. The
whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER
BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable
|
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " +
i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

I see I neglected to answer your question about adding/deleting rows using a
SqlCeResultSet. This works fine - it's just the databinding that you need to
be aware of. For example if you have a list control like a ComboBox and you
add more rows to its databound result set, you won't see them in the
control. The solution is to fill the control with the data manually
including adding/deleting rows as they are added/deleted in the result set
rather than using databinding.

I've found SqlCeResultSet to be a good solution for working with large
amounts of data, both on the storage side as well as performance.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row to
see the row change.

My old DataSet model does raise events to update the row in the bound
DataSet when it updates the underlying database, so I can I could adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or is
there some finer-grained row-relative mechanism to accomplish the same
thing? The effect I am trying to achieve is the same one I get updating
the DataSet for a bound datagrid. That is, if the user is viewing the
rows with the one that changes, they see an update. If not, when they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing mechanism.
Is this true?

Yes, this is what I meant although I didn't realize you weren't updating
the
result set in the grid, but it's still the same principle. The result set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get new
data until you move around in it.

As for what to do about this, one approach is to periodically have the
grid
refresh itself from the data on a timer. The other approach would be to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data in it.
The other difference with a DataSet is that you can add rows to a DataSet
bound to a grid and that works the way you expect, but you shouldn't use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the same
way it does when it is bound to a DataSet and you update a row in the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] = 'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor, create a
button for it, and put the code in the button's click event, only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other
object
(like CurrencyManager) to update the Datagrid, I am updating the
data
source (the first 20 rows in the database with the usual SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls
EndEdit
which
calls Update. If you want to update only a single row, you need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result set
is
not
updated in the bound datagrid? When I inspect the database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If I take
the
loop
out and just updated row 1, it will not be reflected in the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as
the
updates
to SQLCE will occur asychronously in another class. The
whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable |
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

Ginny, thanks for the entry on adding/deleting.

I tried refreshing the SqlCeresultset after updating the data source,
but I took an approach that works well, but I don't know why.

It turns out I didn't have to close the RS, nor did I have to re-issue
the ExecuteResultSet query. Amazingly, all I had to do was re-bind the
datagrid after the update to SQLCe was performed, as in:

dgProducts.DataSource = SqlCeResultSet.ResultSetView;

This leads me to conclude:

- The RS IS sensitive to the changes in the underlying datasource, the
datagrid is NOT
- The datagrid VISIBLE rows, are not being refreshed unless, as you
stated in an earlier post, you MOVE through (read what I found: CLICK
THROUGH) the rows that changed in the datasource.

The only undesirable effect is that, of course, re-binding (as I knew
from re-binding using DataSets) causes the currency manager position to
move to the first row. That's fine, if the app is not depending on the
selected datagrid row to, for example, display detail data. However,
that is exactly how our apps work.

Is there no finer-grained mechanism to tell th datagrid to refresh ONLY
the rows that were affected, either with a bindingsource or
programmatically moving through the row(s) that were affected??

I haven't noticed any flashing when I do this, but if you do when you get a
chance to try it, please let me know.

Although SqlCeResultSet is a DataReader and inherits from SqlCeDataReader,
reissuing that ExecuteResultSet query should be quite fast since you don't
need to iterate though all the records that match the query. The DataGrid
control (when you bind it to the new result set) will only fetch the data
for the visible rows, so that should also be pretty fast.

Let me know how this works out for you,

--
Ginny Caughey
Device Application Development MVP


One observation here is that when I did close the resultset, the
datagrid refreshed its view with "X's". I would assume (and will try
tonight), that if I close and then immediately re-issue the
ExecuteResultSet, there will be some undesirable flashing. If so, how
can I prevent such flashing? That's why I asked if there was a more
finer-grained row relative way of coaxing the datagrid to display the
changes only to that row.

However, what I think you are saying here is that if I want to buy into
the use of SqlCeResultSet, I have realize that what it is doing behind
the scenes is entirely dependent on re-issuing a DataReader query on
the underlying source, so that's what I have to do.
As far as I've been able to figure out, ExecuteResultSet is exactly what
you
want. Once you get the new result set from doing that, then when you bind
that new result set to the grid, you'll see the new data, and the whole
operation should be pretty fast. You can use the old SqlCeConnection
object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time. Make
sure
you close the old result set (which calls Dispose internally) before
issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row to
see the row change.

My old DataSet model does raise events to update the row in the bound
DataSet when it updates the underlying database, so I can I could adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or is
there some finer-grained row-relative mechanism to accomplish the same
thing? The effect I am trying to achieve is the same one I get updating
the DataSet for a bound datagrid. That is, if the user is viewing the
rows with the one that changes, they see an update. If not, when they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing mechanism.
Is this true?


Ginny Caughey [MVP] wrote:
Yes, this is what I meant although I didn't realize you weren't
updating
the
result set in the grid, but it's still the same principle. The result
set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go get
new
data until you move around in it.

As for what to do about this, one approach is to periodically have the
grid
refresh itself from the data on a timer. The other approach would be
to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data in
it.
The other difference with a DataSet is that you can add rows to a
DataSet
bound to a grid and that works the way you expect, but you shouldn't
use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row 2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in the
DataGrid, the grid calls EndEdit which calls Update". I thought the
Datagrid would update by itself without any user interaction, the
same
way it does when it is bound to a DataSet and you update a row in
the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP" in
the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor,
create a
button for it, and put the code in the button's click event,
only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any other
object
(like CurrencyManager) to update the Datagrid, I am updating
the
data
source (the first 20 rows in the database with the usual SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using
ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This
works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid calls
EndEdit
which
calls Update. If you want to update only a single row, you
need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the result
set
is
not
updated in the bound datagrid? When I inspect the
database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If I
take
the
loop
out and just updated row 1, it will not be reflected in
the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue, as
the
updates
to SQLCE will occur asychronously in another class. The
whole
point
in

binding and using ResultSetOptions.Sensitive was that any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType = System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products ORDER
BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable
|
ResultSetOptions.Sensitive | ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " +
i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

Thanks for the update. I don't know of a finer-grained approach to
refreshing the DataGrid unless you take over all the display manually.
Perhaps a DataGrid expert like Ilya will jump in if there's something I'm
missing. You can programmatically move through a DataGrid by using the
DataGrid.CurrentCell property, so maybe that will do what you want.

--
Ginny Caughey
Device Application Development MVP


Ginny, thanks for the entry on adding/deleting.

I tried refreshing the SqlCeresultset after updating the data source,
but I took an approach that works well, but I don't know why.

It turns out I didn't have to close the RS, nor did I have to re-issue
the ExecuteResultSet query. Amazingly, all I had to do was re-bind the
datagrid after the update to SQLCe was performed, as in:

dgProducts.DataSource = SqlCeResultSet.ResultSetView;

This leads me to conclude:

- The RS IS sensitive to the changes in the underlying datasource, the
datagrid is NOT
- The datagrid VISIBLE rows, are not being refreshed unless, as you
stated in an earlier post, you MOVE through (read what I found: CLICK
THROUGH) the rows that changed in the datasource.

The only undesirable effect is that, of course, re-binding (as I knew
from re-binding using DataSets) causes the currency manager position to
move to the first row. That's fine, if the app is not depending on the
selected datagrid row to, for example, display detail data. However,
that is exactly how our apps work.

Is there no finer-grained mechanism to tell th datagrid to refresh ONLY
the rows that were affected, either with a bindingsource or
programmatically moving through the row(s) that were affected??

I haven't noticed any flashing when I do this, but if you do when you get
a
chance to try it, please let me know.

Although SqlCeResultSet is a DataReader and inherits from
SqlCeDataReader,
reissuing that ExecuteResultSet query should be quite fast since you
don't
need to iterate though all the records that match the query. The DataGrid
control (when you bind it to the new result set) will only fetch the data
for the visible rows, so that should also be pretty fast.

Let me know how this works out for you,

--
Ginny Caughey
Device Application Development MVP


One observation here is that when I did close the resultset, the
datagrid refreshed its view with "X's". I would assume (and will try
tonight), that if I close and then immediately re-issue the
ExecuteResultSet, there will be some undesirable flashing. If so, how
can I prevent such flashing? That's why I asked if there was a more
finer-grained row relative way of coaxing the datagrid to display the
changes only to that row.

However, what I think you are saying here is that if I want to buy into
the use of SqlCeResultSet, I have realize that what it is doing behind
the scenes is entirely dependent on re-issuing a DataReader query on
the underlying source, so that's what I have to do.

Ginny Caughey [MVP] wrote:
As far as I've been able to figure out, ExecuteResultSet is exactly
what
you
want. Once you get the new result set from doing that, then when you
bind
that new result set to the grid, you'll see the new data, and the
whole
operation should be pretty fast. You can use the old SqlCeConnection
object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time. Make
sure
you close the old result set (which calls Dispose internally) before
issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere
scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row
to
see the row change.

My old DataSet model does raise events to update the row in the
bound
DataSet when it updates the underlying database, so I can I could
adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or
is
there some finer-grained row-relative mechanism to accomplish the
same
thing? The effect I am trying to achieve is the same one I get
updating
the DataSet for a bound datagrid. That is, if the user is viewing
the
rows with the one that changes, they see an update. If not, when
they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing
mechanism.
Is this true?


Ginny Caughey [MVP] wrote:
Yes, this is what I meant although I didn't realize you weren't
updating
the
result set in the grid, but it's still the same principle. The
result
set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go
get
new
data until you move around in it.

As for what to do about this, one approach is to periodically have
the
grid
refresh itself from the data on a timer. The other approach would
be
to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data
in
it.
The other difference with a DataSet is that you can add rows to a
DataSet
bound to a grid and that works the way you expect, but you
shouldn't
use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row
2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in
the
DataGrid, the grid calls EndEdit which calls Update". I thought
the
Datagrid would update by itself without any user interaction, the
same
way it does when it is bound to a DataSet and you update a row in
the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update
the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP"
in
the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor,
create a
button for it, and put the code in the button's click event,
only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any
other
object
(like CurrencyManager) to update the Datagrid, I am
updating
the
data
source (the first 20 rows in the database with the usual
SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using
ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This
works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid
calls
EndEdit
which
calls Update. If you want to update only a single row,
you
need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the
result
set
is
not
updated in the bound datagrid? When I inspect the
database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If
I
take
the
loop
out and just updated row 1, it will not be reflected in
the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue,
as
the
updates
to SQLCE will occur asychronously in another class.
The
whole
point
in

binding and using ResultSetOptions.Sensitive was that
any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType =
System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products
ORDER
BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable
|
ResultSetOptions.Sensitive |
ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " +
i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
A

aknittel

I tried DataGrid.CurrentCell, moving the row from 0 to 1 anf back to 0.
Apparently, that is not the equivalent of clicking in the row. Also
tried setting DataGrid.CurrentCell and invoking:

dgProducts.BindingContext[dgProducts.DataSource].EndCurrentEdit();

No dice. Just what IS the equivalent of clicking through? I could call
the DataGrid click event I suppose.
Thanks for the update. I don't know of a finer-grained approach to
refreshing the DataGrid unless you take over all the display manually.
Perhaps a DataGrid expert like Ilya will jump in if there's something I'm
missing. You can programmatically move through a DataGrid by using the
DataGrid.CurrentCell property, so maybe that will do what you want.

--
Ginny Caughey
Device Application Development MVP


Ginny, thanks for the entry on adding/deleting.

I tried refreshing the SqlCeresultset after updating the data source,
but I took an approach that works well, but I don't know why.

It turns out I didn't have to close the RS, nor did I have to re-issue
the ExecuteResultSet query. Amazingly, all I had to do was re-bind the
datagrid after the update to SQLCe was performed, as in:

dgProducts.DataSource = SqlCeResultSet.ResultSetView;

This leads me to conclude:

- The RS IS sensitive to the changes in the underlying datasource, the
datagrid is NOT
- The datagrid VISIBLE rows, are not being refreshed unless, as you
stated in an earlier post, you MOVE through (read what I found: CLICK
THROUGH) the rows that changed in the datasource.

The only undesirable effect is that, of course, re-binding (as I knew
from re-binding using DataSets) causes the currency manager position to
move to the first row. That's fine, if the app is not depending on the
selected datagrid row to, for example, display detail data. However,
that is exactly how our apps work.

Is there no finer-grained mechanism to tell th datagrid to refresh ONLY
the rows that were affected, either with a bindingsource or
programmatically moving through the row(s) that were affected??

I haven't noticed any flashing when I do this, but if you do when you get
a
chance to try it, please let me know.

Although SqlCeResultSet is a DataReader and inherits from
SqlCeDataReader,
reissuing that ExecuteResultSet query should be quite fast since you
don't
need to iterate though all the records that match the query. The DataGrid
control (when you bind it to the new result set) will only fetch the data
for the visible rows, so that should also be pretty fast.

Let me know how this works out for you,

--
Ginny Caughey
Device Application Development MVP


One observation here is that when I did close the resultset, the
datagrid refreshed its view with "X's". I would assume (and will try
tonight), that if I close and then immediately re-issue the
ExecuteResultSet, there will be some undesirable flashing. If so, how
can I prevent such flashing? That's why I asked if there was a more
finer-grained row relative way of coaxing the datagrid to display the
changes only to that row.

However, what I think you are saying here is that if I want to buy into
the use of SqlCeResultSet, I have realize that what it is doing behind
the scenes is entirely dependent on re-issuing a DataReader query on
the underlying source, so that's what I have to do.

Ginny Caughey [MVP] wrote:
As far as I've been able to figure out, ExecuteResultSet is exactly
what
you
want. Once you get the new result set from doing that, then when you
bind
that new result set to the grid, you'll see the new data, and the
whole
operation should be pretty fast. You can use the old SqlCeConnection
object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time. Make
sure
you close the old result set (which calls Dispose internally) before
issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere
scrolling
through the datagrid doesn't show the updated row ("moving around in
it" as you say). It seems the user has to click THRU the updated row
to
see the row change.

My old DataSet model does raise events to update the row in the
bound
DataSet when it updates the underlying database, so I can I could
adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this is
just re-issue the SqlCeCommand.ExecuteResultSet original query, or
is
there some finer-grained row-relative mechanism to accomplish the
same
thing? The effect I am trying to achieve is the same one I get
updating
the DataSet for a bound datagrid. That is, if the user is viewing
the
rows with the one that changes, they see an update. If not, when
they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing
mechanism.
Is this true?


Ginny Caughey [MVP] wrote:
Yes, this is what I meant although I didn't realize you weren't
updating
the
result set in the grid, but it's still the same principle. The
result
set
is
sensitive in that any changes made by anything else are immediately
reflected in the underlying data, but the grid doesn't know to go
get
new
data until you move around in it.

As for what to do about this, one approach is to periodically have
the
grid
refresh itself from the data on a timer. The other approach would
be
to
have
the operation that makes the changes raise an event that ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid to
refresh
itself from the DataSet, the DataSet would still have the old data
in
it.
The other difference with a DataSet is that you can add rows to a
DataSet
bound to a grid and that works the way you expect, but you
shouldn't
use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row
2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row in
the
DataGrid, the grid calls EndEdit which calls Update". I thought
the
Datagrid would update by itself without any user interaction, the
same
way it does when it is bound to a DataSet and you update a row in
the
DataSet.

Why does it behave the way it does? How can I get it to detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just update
the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product Name] =
'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated "PPP"
in
the
database as independently confirmed by taking the .sdf file and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor,
create a
button for it, and put the code in the button's click event,
only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any
other
object
(like CurrencyManager) to update the Datagrid, I am
updating
the
data
source (the first 20 rows in the database with the usual
SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using
ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1. This
works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid
calls
EndEdit
which
calls Update. If you want to update only a single row,
you
need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the
result
set
is
not
updated in the bound datagrid? When I inspect the
database,
ALL
rows
(ProductID 1 to 20) have been updated as expected. If
I
take
the
loop
out and just updated row 1, it will not be reflected in
the
grid.
This
ONLY happens with the first row.

It is not an option to use the SQLCeResultSet.SetValue,
as
the
updates
to SQLCE will occur asychronously in another class.
The
whole
point
in

binding and using ResultSetOptions.Sensitive was that
any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly = Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType =
System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products
ORDER
BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable
|
ResultSetOptions.Sensitive |
ResultSetOptions.Updatable);


dgProducts.DataSource = sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " +
i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 
G

Ginny Caughey [MVP]

I don't know if that would work either. Sorry but I'm out of ideas at the
moment other than binding to a new result set. Maybe somebody else will
think of something to try.

--
Ginny Caughey
Device Application Development MVP


I tried DataGrid.CurrentCell, moving the row from 0 to 1 anf back to 0.
Apparently, that is not the equivalent of clicking in the row. Also
tried setting DataGrid.CurrentCell and invoking:

dgProducts.BindingContext[dgProducts.DataSource].EndCurrentEdit();

No dice. Just what IS the equivalent of clicking through? I could call
the DataGrid click event I suppose.
Thanks for the update. I don't know of a finer-grained approach to
refreshing the DataGrid unless you take over all the display manually.
Perhaps a DataGrid expert like Ilya will jump in if there's something I'm
missing. You can programmatically move through a DataGrid by using the
DataGrid.CurrentCell property, so maybe that will do what you want.

--
Ginny Caughey
Device Application Development MVP


Ginny, thanks for the entry on adding/deleting.

I tried refreshing the SqlCeresultset after updating the data source,
but I took an approach that works well, but I don't know why.

It turns out I didn't have to close the RS, nor did I have to re-issue
the ExecuteResultSet query. Amazingly, all I had to do was re-bind the
datagrid after the update to SQLCe was performed, as in:

dgProducts.DataSource = SqlCeResultSet.ResultSetView;

This leads me to conclude:

- The RS IS sensitive to the changes in the underlying datasource, the
datagrid is NOT
- The datagrid VISIBLE rows, are not being refreshed unless, as you
stated in an earlier post, you MOVE through (read what I found: CLICK
THROUGH) the rows that changed in the datasource.

The only undesirable effect is that, of course, re-binding (as I knew
from re-binding using DataSets) causes the currency manager position to
move to the first row. That's fine, if the app is not depending on the
selected datagrid row to, for example, display detail data. However,
that is exactly how our apps work.

Is there no finer-grained mechanism to tell th datagrid to refresh ONLY
the rows that were affected, either with a bindingsource or
programmatically moving through the row(s) that were affected??


Ginny Caughey [MVP] wrote:
I haven't noticed any flashing when I do this, but if you do when you
get
a
chance to try it, please let me know.

Although SqlCeResultSet is a DataReader and inherits from
SqlCeDataReader,
reissuing that ExecuteResultSet query should be quite fast since you
don't
need to iterate though all the records that match the query. The
DataGrid
control (when you bind it to the new result set) will only fetch the
data
for the visible rows, so that should also be pretty fast.

Let me know how this works out for you,

--
Ginny Caughey
Device Application Development MVP


One observation here is that when I did close the resultset, the
datagrid refreshed its view with "X's". I would assume (and will try
tonight), that if I close and then immediately re-issue the
ExecuteResultSet, there will be some undesirable flashing. If so,
how
can I prevent such flashing? That's why I asked if there was a more
finer-grained row relative way of coaxing the datagrid to display
the
changes only to that row.

However, what I think you are saying here is that if I want to buy
into
the use of SqlCeResultSet, I have realize that what it is doing
behind
the scenes is entirely dependent on re-issuing a DataReader query on
the underlying source, so that's what I have to do.

Ginny Caughey [MVP] wrote:
As far as I've been able to figure out, ExecuteResultSet is exactly
what
you
want. Once you get the new result set from doing that, then when
you
bind
that new result set to the grid, you'll see the new data, and the
whole
operation should be pretty fast. You can use the old
SqlCeConnection
object
and SelCeCommand object if you choose to (perhaps using class-level
variables for those), but you'll have a new result set each time.
Make
sure
you close the old result set (which calls Dispose internally)
before
issuing
ExecuteResultSet again each time so you don't leak resources.

--
Ginny Caughey
Device Application Development MVP


Ahh, OK. I began to realize this last night. However, mere
scrolling
through the datagrid doesn't show the updated row ("moving around
in
it" as you say). It seems the user has to click THRU the updated
row
to
see the row change.

My old DataSet model does raise events to update the row in the
bound
DataSet when it updates the underlying database, so I can I could
adapt
that for SQLCEResult.

Once the UI gets the event, is the most efficient way to do this
is
just re-issue the SqlCeCommand.ExecuteResultSet original query,
or
is
there some finer-grained row-relative mechanism to accomplish the
same
thing? The effect I am trying to achieve is the same one I get
updating
the DataSet for a bound datagrid. That is, if the user is viewing
the
rows with the one that changes, they see an update. If not, when
they
scroll to it, they see the updated row.

I had high hopes that SQLCeResultSet would solve my data capacity
problems with DataSet (3 copies in memory), but you seem to
indicate
that if rows are added and possibly deleted, I will have trouble
pursuing this model with SQLCeResultSet as the key cacheing
mechanism.
Is this true?


Ginny Caughey [MVP] wrote:
Yes, this is what I meant although I didn't realize you weren't
updating
the
result set in the grid, but it's still the same principle. The
result
set
is
sensitive in that any changes made by anything else are
immediately
reflected in the underlying data, but the grid doesn't know to
go
get
new
data until you move around in it.

As for what to do about this, one approach is to periodically
have
the
grid
refresh itself from the data on a timer. The other approach
would
be
to
have
the operation that makes the changes raise an event that
ultimately
causes
the grid to get new data.

What's different about a DataSet is that even if you tell a grid
to
refresh
itself from the DataSet, the DataSet would still have the old
data
in
it.
The other difference with a DataSet is that you can add rows to
a
DataSet
bound to a grid and that works the way you expect, but you
shouldn't
use
databinding with a result set that you need to add rows to.

--
Ginny Caughey
Device Application Development MVP


Weird. I clicked off row 1 in the datagrid (by clicking on row
2),
clicked again on row 1, and the value changed!

Ginny, is this what you meant by "When you move to a new row
in
the
DataGrid, the grid calls EndEdit which calls Update". I
thought
the
Datagrid would update by itself without any user interaction,
the
same
way it does when it is bound to a DataSet and you update a row
in
the
DataSet.

Why does it behave the way it does? How can I get it to
detect a
change and move to the row that was changed?

(e-mail address removed) wrote:
Actually, what I tried to do was ditch the loop and just
update
the
first row as in:

sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET [Product
Name] =
'PPP'
WHERE
[Product ID] = 1";
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();

I have stepped through this code and recs = 1.

Also, Product ID 1 (Product Name field) HAS been updated
"PPP"
in
the
database as independently confirmed by taking the .sdf file
and
reading
it directly with VS 2005.


Graham McKechnie wrote:
Are you sure i in your loop matches your product id. Have
you
stepped
through it in the debugger. What is the result of recs when
cmd.ExecuteNonQuery excutes for your problem records.

Why don't you ditch the data binding and try it manually?

Graham

Here is something even more bizarre.

If I take the following code out of the Form constructor,
create a
button for it, and put the code in the button's click
event,
only
rows
11 thru 20 are updated in the datagrid.

for (int i = 1; i <= 20; i++)
{
sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products SET
[Product
Name]
=
'DDD'
WHERE [Product ID] = " + i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();
}


==============
(e-mail address removed) wrote:
Ginny, thanks for replying on Sunday!

Maybe I should detail what I am expecting.

I am not using SQLCeResultSet to update the row, or any
other
object
(like CurrencyManager) to update the Datagrid, I am
updating
the
data
source (the first 20 rows in the database with the usual
SQL
Update
statement).

I am expecting to see the datagrid update all 20 rows
automatically
as
a result of that because it is using
ResultSetOptions.Sensitive.
It
shows rows 2-20 are updated with "XXX", but not row 1.
This
works
fine
with the Datagrid bound to a table in a dataset.


Ginny Caughey [MVP] wrote:
When you move to a new row in the DataGrid, the grid
calls
EndEdit
which
calls Update. If you want to update only a single row,
you
need
to
call
EndEdit yourself.

--
Ginny Caughey
Device Application Development MVP


Can someone explain to me why the first row in the
result
set
is
not
updated in the bound datagrid? When I inspect the
database,
ALL
rows
(ProductID 1 to 20) have been updated as expected.
If
I
take
the
loop
out and just updated row 1, it will not be reflected
in
the
grid.
This
ONLY happens with the first row.

It is not an option to use the
SQLCeResultSet.SetValue,
as
the
updates
to SQLCE will occur asychronously in another class.
The
whole
point
in

binding and using ResultSetOptions.Sensitive was
that
any
changes in
the data source would be reflected.


===============================================


Assembly myAssembly =
Assembly.GetExecutingAssembly();


string DBFolder =
Path.GetDirectoryName(myAssembly.GetName().CodeBase);



sqlCEConnection = new SqlCeConnection("data
source='" +
DBFolder
+
"\\"

+ "Northwind.sdf" + "'; mode=Exclusive;");


sqlCEConnection.Open();


sqlCeCommand = sqlCEConnection.CreateCommand();
sqlCeCommand.CommandType =
System.Data.CommandType.Text;
sqlCeCommand.CommandText = "SELECT * FROM Products
ORDER
BY
[Product
ID]";


sqlCeResultSet =
sqlCeCommand.ExecuteResultSet(ResultSetOptions.Scrollable
|
ResultSetOptions.Sensitive |
ResultSetOptions.Updatable);


dgProducts.DataSource =
sqlCeResultSet.ResultSetView;


for (int i = 1; i <= 20; i++)
{
sqlCeCommand =
sqlCEConnection.CreateCommand();
sqlCeCommand.CommandText = "UPDATE Products
SET
[Product
Name]
= 'XXX'
WHERE [Product ID] = " +
i.ToString();
int recs = sqlCeCommand.ExecuteNonQuery();
sqlCeCommand.Dispose();


}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top