Typed Dataset event handling problem

G

Guest

I have a standard typed dataset (.net 2005). And created a separete class
file to handle the RowChanging event. The dataset name is dalCadastro and the
datatable is pessoa. The code I wrote to extend the dataset and handle the
event is as follows:

public partial class dalCadastro
{
public partial class pessoaDataTable
{
public override void BeginInit()
{
base.BeginInit();
this.RowChanging +=
new DataRowChangeEventHandler(Validate);
}

void Validate(object sender, DataRowChangeEventArgs e)
{
throw new Exception("Can not change!");
}
}
}

It compiles OK. But when the page is loaded, the exception I created was
thrown. Why if the event is only when a column is changing ?

I tried to test if( e.Row.RowState == DataRowState.Modified ), but not
works. The state is allways Detached ... Even if I issued the update.

I tried test if (e.Action == DataRowAction.Change), but do not work too.

I'm using a form view and a object datasource configured to use this typed
dataset. All select, insert, delete and update works fine, but the Event
handling not.

What is the correct form for this type of event handling or what
verifications I need to do in the event handler code ?

I tried several internet samples, but none work, even compile.

An observation, the code was writen with the help of the VS 2005 IDE when
i'm was typing the code.

What is the solution please ?

--- I tried a more strongly typed handling (that is possible in VS 2005) ...
but the same behavior continues:

public partial class dalCadastro
{
public partial class pessoaDataTable
{
public override void BeginInit()
{
base.BeginInit();
Here-->> this.pessoaRowChanging += new
pessoaRowChangeEventHandler(Validate);
}

void Validate(object sender, -->> Here pessoaRowChangeEvent e)
{
throw new Exception("Cannot change");
}
}
}
 
G

Guest

I tried follow a sample in
http://msdn2.microsoft.com/en-us/library/1120xds5.aspx

The code was modied as follows:

public partial class dalCadastro
{
public partial class pessoaDataTable
{
public override void EndInit()
{
base.EndInit();
pessoaRowChanging += Validate;
}

void Validate(object sender, pessoaRowChangeEvent e)
{
throw new Exception("Cannot change");
}
}
}

But the same behavior occurs. On the page load, the exception (coded in the
event handler) was thrown !!!!
 
G

Guest

I discover the reason, but not the solution. Examining the stack trace I
discovered that the object datasource when call the Select method, the typed
dataset class issues AcceptChanges() and CommitRow() ... this fires my event
handler.

How to handle solve this ? Appears to be a room with no exit.

Follow the relevant stack trace :

pessoaDataTable.Validate(Object sender, pessoaRowChangeEvent e) in
c:\dotNet\SMS\App_Code\Business\bllCadastro.cs:19
pessoaDataTable.OnRowChanged(DataRowChangeEventArgs e) in
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET
Files\sms\61162d46\e25f7ec2\App_Code.4-hlcjqb.1.cs:466
System.Data.DataTable.OnRowChanged(DataRowChangeEventArgs args, DataRow
eRow, DataRowAction eAction) +87
System.Data.DataTable.CommitRow(DataRow row) +86
System.Data.DataRow.AcceptChanges() +310
System.Data.DataTable.LoadDataRow(Object[] values, Boolean
fAcceptChanges) +397
System.Data.ProviderBase.SchemaMapping.LoadDataRow() +167
 
J

Joel Holder

I have the same issue. I want to detect row changes in a typed dataset. Everytime the page loads, I get an add and a commit event for every row as it gets loaded. Did you ever find the solution?

EggHeadCafe.com - .NET Developer Portal of Choice
http://www.eggheadcafe.com
 
O

Otis Mukinfus

Joel,

Attach event handlers only after dataset/datatable is loaded.

I hadn't thought of that, Miha. It's a good solution.

Usually when I don't want things to happen during loads I will declare a private
bool named loading in the class and set it to true at the beginning of the
form's Load event and then set it to false at the end of the event. Then any
vents I don't want to process will have:

if(loading)
{
return;
}

at the beginning.


Good luck with your project,

Otis Mukinfus
http://www.arltex.com
http://www.tomchilders.com
 
M

Miha Markic [MVP C#]

Hi Otis,

Otis Mukinfus said:
I hadn't thought of that, Miha. It's a good solution.

Usually when I don't want things to happen during loads I will declare a
private
bool named loading in the class and set it to true at the beginning of the
form's Load event and then set it to false at the end of the event. Then
any
vents I don't want to process will have:

if(loading)
{
return;
}

at the beginning.

This is a solution however much slower becuase the event is still handled..
 
G

Guest

A friend tell me that it happens because when the page loads, the internal
code for the Typed DataSet calls the Fill method for the datatable, and
consequently this makes the rows to be changed. He sugested that I copy
DataSet.Designer.cs to another file. Delete the Fill method in the original
DataSet.Designer.cs and in the new dataset.cs file, re-write the Fill method
and register the event after the adapter's Fill method call. This will avoid
the event to be fired when the page lods, because in the normal situation the
event is already registered, and when the page loads it is fired. The boring
thing about this solution is when you reconfigure you Typed Dataset, you must
delete de fill method in the original DatasetDesigner.cs ... you must delete
because if not, you will have two Fill methods for the datatable. Deleting,
the compiler will consider you version on the other .cs file, that implement
the datatable's Fill method diferently.

I thynked that the correct thing was only create a separate file and write
code to register for the event using the "partial" keyword. The only work
more where to test the e.Action and e.Row.State ... I thinked that the
following code resolved my problem, but not. Both in the page load, as in the
Update action in my form view, these values are the same. Look ... its a
standard code (TesteTD is the name of the typed dataset and tab_smsDataTable
is the name of the datatable i'm subscribing to the event. The result of this
code was: the page loads OK, but when I update, the test exception is not
thrown ... because the event argument values are allways the same.

public partial class TesteTD
{
public partial class tab_smsDataTable
{
public override void EndInit()
{
base.EndInit();
this.tab_smsRowChanging += new
tab_smsRowChangeEventHandler(Validate);
}

void Validate(object sender, tab_smsRowChangeEvent e)
{
if (e.Action != DataRowAction.Add &&
e.Row.RowState != DataRowState.Added)
{
throw new Exception("Cannot Change!");
}
}
}
}

I'm yet investigating a more elegant solution ... I'm doing somes tests and
working with this guy from Microsoft. And any good news be sure I'll reply to
you.

Best Regards,
 
G

Guest

Hi Miha,

Yes, but in a case that I have the Typed DataSet and I bound it to a
ObjectDataSource, and a FormView bouded to this ObjectDataSource in a ASP.NET
2.0 Page ? When the page loads, the fill is called automatically. The corret
way (I thynk, and many articles, including Microsoft articles) orient you to
do some like this following code, but the e.Action and e.Row.RowState remains
the same booth when the page loads and when a Update operation occurs in the
FormView.

I thynk its a bug, and the workarroud to avoid this are very non-elegant and
needs rewok every time I reconfigure the Typed DataSet.

public partial class TesteTD
{
public partial class tab_smsDataTable
{
public override void EndInit()
{
base.EndInit();
this.tab_smsRowChanging += new
tab_smsRowChangeEventHandler(Validate);
}

void Validate(object sender, tab_smsRowChangeEvent e)
{
if (e.Action != DataRowAction.Add &&
e.Row.RowState != DataRowState.Added)
{
throw new Exception("Não pode alerar!");
}
}
}
}

--
Lucas Ponzo
..NET Solutions Architect/Engineer
Override Software


Miha Markic said:
Joel,

Attach event handlers only after dataset/datatable is loaded.

--
Miha Markic [MVP C#, INETA Country Leader for Slovenia]
RightHand .NET consulting & development www.rthand.com
Blog: http://cs.rthand.com/blogs/blog_with_righthand/

in message
I have the same issue. I want to detect row changes in a typed dataset.
Everytime the page loads, I get an add and a commit event for every row as
it gets loaded. Did you ever find the solution?

EggHeadCafe.com - .NET Developer Portal of Choice
http://www.eggheadcafe.com
 
G

Guest

Hi Othis,

But how to do it when the event handler is on another layer of the
application ? In this case, in a event handler to being registered in an
extended TypedDataSet Class ?
 
G

Guest

Hi Joel,

Why we cannot control when the Row is really Changing or Changed, (or in
other states) using the event handler argument.

The reason is that it is ASP.net Project. In Winform, the DataTable will be
stored in memory after we create it. When DataTable has been changed, Winform
can compare it with the DataTable in memory.

So we can know which row has been changed. But in ASP.net, there is no
memory to store this DataTable. The DataTable will be generated everytime if
there is a http request. In our case, the OjectDataSource will create the
table when there is a
Http Request, then bind it to FormView.

The most important thing is that the behavior after we click "Update" in
"Edit Mode". It is something different as we think before:
The OjectDataSource create a table and change the row then update to
Database. But the actual behavior is that ObjectDataSource will update the
row
directly to Database and then create a new DataTable from the database.

There is no DataTable in memory when we click "Update" button, so we cannot
catch the DataTable's "RowChanging" event. There is always a new DataTable
created by ObjectDataSource. There are always the "add" and "Commit" Event.

For these reasons, I'm afraid we cannot use "RowChanging" event. It will not
work as we expect in ASP.net, even through it work fine in WinForm Project.

We should have to do some code in FormViewe rather than in Typed Dataset.

For example:

Add follow code in Form Viewe Item Updating Event.

protected void FormView1_ItemUpdating1(object sender,
FormViewUpdateEventArgs e)
{
Response.Write("can not be edit");
e.Cancel = true;
}

It is some restriction from ASP.net not ADO.net.

But I have some ideas:

1) Create a wrapper bussiness class to use in the object datasource and in
the update method do the validations.

2) Create a derived class that caches the datatable and work like in
WinForms ... it's a more complex task.

Best Regards,
 

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

Top