Hi!

I create a new row in dataset "ds" and press "save" where following is done:

ds = the full dataset, that was loaded at the start up of the form
dsChanges = that is simply ds.GetChanges(). this dataset is the one sent
down to "data layer"

Step 1.

'We can see that the new row is created - note the status "Added":
ds.tables("PriceLists").rows.count ---> 21 Integer
ds.Tables("PriceLists").Rows(20).Rowstate ---> Added
System.Data.DataRowState

'Note that I have not entered ID for PK column - that is automaticly
generated in "data layer":
ds.Tables("PriceLists").Rows(20).Item("PriceListID") {System.DBNull} Object

'We can also see that the "difference dataset" contains the new row:
dsChanges.Tables("PriceLists").Rows.Count ---> 1 Integer
'...and of course is the PK column still correctly null:
dschanges.tables("PriceLists").Rows(0).Item("PriceListID") {System.DBNull}
Object

Step 2.

'I send down dsChanges to data layer. The data layer returns a dsChanges
that update is done on (using stored procedures...).
'We can no see that the row has successfully been added to the database,
'with a "Identity" (MSSQL) value as PK. Perfect!:
dschanges.tables("PriceLists").Rows(0).Item("PriceListID") 1635 {Integer}
Object

Step 3.

'Let me now simply do a "ds.Merge(dsChanges)" and have a new look at the
values.
'What! - Merge has added a NEW row instead of updating the newly created
one.
ds.Tables("PriceLists").Rows.Count ---> 22 Integer

'The row that was added by me was not touched by the Merge (status still
"Added") - see:
ds.Tables("PriceLists").Rows(20).Rowstate ---> Added
System.Data.DataRowState
ds.Tables("PriceLists").Rows(20).Item("PriceListID") {System.DBNull} Object

'But the - NOT WANTED - new row that Merge created has the new PK value.
ds.Tables("PriceLists").Rows(21).Item("PriceListID") 1635 {Integer} Object

Merge fails to understand how to merge the newly created row that was
bounced to data layer and complemented with the "automaticly created unique
primary key value" (quote from help file above).

Can you understand my problem?
Working with the combination of "GetChanges" / "Merge" / "MSSQL - Identity
column" must be a common scenario.
The scenario should really work - MS is describing it in the help file
referred to above ;-)

I really hope I am doing something wrong - but what ?

Can it be the lack of .PrimaryKey constraint on the DataTable that makes it
impossible for Merge to find the row to update?
BUT I can NOT have a .PrimaryKey constraint - as I have understood - because
the client dataset MUST ALLOW the PriceListID column to be NULL until
complemented with "Identity generated PK" by data layer.

Coding in VisualBasic.

Best regards
Benjamin Tengelin, Sweden

Re: DataSet.Merge / auto number on PK -> duplicated rows problem by William

William
Wed Jul 07 08:04:23 CDT 2004

Check out Bill Vaughn's Managing an @@Identity Crisis at www.betav.com ->
Articles -> MSDN. I think one problem is that its looking to match the
same PK values and those are different.

--

W.G. Ryan, eMVP

Have an opinion on the effectiveness of Microsoft Embedded newsgroups?
Let Microsoft know!
https://www.windowsembeddedeval.com/community/newsgroups
"Benjamin" <benjamin@congenialdata.se> wrote in message
news:u$dir3BZEHA.644@tk2msftngp13.phx.gbl...
> Hi!
>
> I create a new row in dataset "ds" and press "save" where following is
done:
>
> ds = the full dataset, that was loaded at the start up of the form
> dsChanges = that is simply ds.GetChanges(). this dataset is the one sent
> down to "data layer"
>
> Step 1.
>
> 'We can see that the new row is created - note the status "Added":
> ds.tables("PriceLists").rows.count ---> 21 Integer
> ds.Tables("PriceLists").Rows(20).Rowstate ---> Added
> System.Data.DataRowState
>
> 'Note that I have not entered ID for PK column - that is automaticly
> generated in "data layer":
> ds.Tables("PriceLists").Rows(20).Item("PriceListID") {System.DBNull}
Object
>
> 'We can also see that the "difference dataset" contains the new row:
> dsChanges.Tables("PriceLists").Rows.Count ---> 1 Integer
> '...and of course is the PK column still correctly null:
> dschanges.tables("PriceLists").Rows(0).Item("PriceListID")
{System.DBNull}
> Object
>
> Step 2.
>
> 'I send down dsChanges to data layer. The data layer returns a dsChanges
> that update is done on (using stored procedures...).
> 'We can no see that the row has successfully been added to the database,
> 'with a "Identity" (MSSQL) value as PK. Perfect!:
> dschanges.tables("PriceLists").Rows(0).Item("PriceListID") 1635 {Integer}
> Object
>
> Step 3.
>
> 'Let me now simply do a "ds.Merge(dsChanges)" and have a new look at the
> values.
> 'What! - Merge has added a NEW row instead of updating the newly created
> one.
> ds.Tables("PriceLists").Rows.Count ---> 22 Integer
>
> 'The row that was added by me was not touched by the Merge (status still
> "Added") - see:
> ds.Tables("PriceLists").Rows(20).Rowstate ---> Added
> System.Data.DataRowState
> ds.Tables("PriceLists").Rows(20).Item("PriceListID") {System.DBNull}
Object
>
> 'But the - NOT WANTED - new row that Merge created has the new PK value.
> ds.Tables("PriceLists").Rows(21).Item("PriceListID") 1635 {Integer}
Object
>
> Merge fails to understand how to merge the newly created row that was
> bounced to data layer and complemented with the "automaticly created
unique
> primary key value" (quote from help file above).
>
> Can you understand my problem?
> Working with the combination of "GetChanges" / "Merge" / "MSSQL - Identity
> column" must be a common scenario.
> The scenario should really work - MS is describing it in the help file
> referred to above ;-)
>
> I really hope I am doing something wrong - but what ?
>
> Can it be the lack of .PrimaryKey constraint on the DataTable that makes
it
> impossible for Merge to find the row to update?
> BUT I can NOT have a .PrimaryKey constraint - as I have understood -
because
> the client dataset MUST ALLOW the PriceListID column to be NULL until
> complemented with "Identity generated PK" by data layer.
>
> Coding in VisualBasic.
>
> Best regards
> Benjamin Tengelin, Sweden
>
>
>



Re: DataSet.Merge / auto number on PK -> duplicated rows problem by Benjamin

Benjamin
Wed Jul 07 09:42:23 CDT 2004

This is a multi-part message in MIME format.

------=_NextPart_000_000F_01C46441.60F53130
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Hi!

I looked at the article: =
http://msdn.microsoft.com/library/default.asp?url=3D/library/en-us/dnadon=
et/html/manidcrisis.asp
and followed it by hooked on PrimaryKey and AutoIncrements settings. =
But...
This article is a nice suggestion if your are satisfied with the fact =
that you, after saving, continue (!) to work with the client side (!) =
generated AutoIncrements (-1,-2,-3 ...) until you do a fresh reload of =
the DataSet (e g restarts the form). It is first when you do a complete =
DataSet reload that you get the real server (!) side AutoIncrements.

But MSDN documentation "promises" more...
http://msdn.microsoft.com/library/default.asp?url=3D/library/en-us/cpref/=
html/frlrfsystemdatadatasetclassmergetopic2.asp

It says (and that is exactly what I want to achive):

In a client application, it is usual to have a single button that the =
user can click that gathers the changed data and validates it before =
sending it back to a middle tier component. In this scenario, the =
GetChanges method is first invoked. That method returns a second DataSet =
optimized for validating and merging. This second DataSet object =
contains only the DataTable and DataRow objects that were changed, =
resulting in a subset of the original DataSet. This subset is generally =
smaller, and thus more efficiently passed back to a middle tier =
component. The middle tier component will then update the original data =
source with the changes through stored procedures. The middle tier can =
then send back either a new DataSet that includes original data and the =
latest data from the data source (by running the original query again), =
or it can send back the subset with any changes that have been made to =
it from the data source. (For example, if the data source automatically =
creates unique primary key values, these values can be propagated back =
to the client application.) In either case, the returned DataSet can be =
merged back into the client application's original DataSet with the =
Merge method.

This documentation doesn't say that you have to do a total reload of the =
DataSet to get the server side generated AutoIncrements.
The new row should simple be bounced down to data layer and the new row =
in the client dataset should be "replaced"/"complemented" by using the =
.Merge-method.
Not added !!!

Anyone that has implemented the above nice description by Microsoft?

Best regards
Benjamin Tengelin, Sweden


"William Ryan eMVP" <dotnetguru@comcast.nospam.net> wrote in message =
news:ugKb4ICZEHA.2216@TK2MSFTNGP10.phx.gbl...
> Check out Bill Vaughn's Managing an @@Identity Crisis at www.betav.com =
->
> Articles -> MSDN. I think one problem is that its looking to match =
the
> same PK values and those are different.
>=20
> --=20
>=20
> W.G. Ryan, eMVP
>=20
> Have an opinion on the effectiveness of Microsoft Embedded newsgroups?
> Let Microsoft know!
> https://www.windowsembeddedeval.com/community/newsgroups
> "Benjamin" <benjamin@congenialdata.se> wrote in message
> news:u$dir3BZEHA.644@tk2msftngp13.phx.gbl...
> > Hi!
> >
> > I create a new row in dataset "ds" and press "save" where following =
is
> done:
> >
> > ds =3D the full dataset, that was loaded at the start up of the form
> > dsChanges =3D that is simply ds.GetChanges(). this dataset is the =
one sent
> > down to "data layer"
> >
> > Step 1.
> >
> > 'We can see that the new row is created - note the status "Added":
> > ds.tables("PriceLists").rows.count ---> 21 Integer
> > ds.Tables("PriceLists").Rows(20).Rowstate ---> Added
> > System.Data.DataRowState
> >
> > 'Note that I have not entered ID for PK column - that is =
automaticly
> > generated in "data layer":
> > ds.Tables("PriceLists").Rows(20).Item("PriceListID") =
{System.DBNull}
> Object
> >
> > 'We can also see that the "difference dataset" contains the new =
row:
> > dsChanges.Tables("PriceLists").Rows.Count ---> 1 Integer
> > '...and of course is the PK column still correctly null:
> > dschanges.tables("PriceLists").Rows(0).Item("PriceListID")
> {System.DBNull}
> > Object
> >
> > Step 2.
> >
> > 'I send down dsChanges to data layer. The data layer returns a =
dsChanges
> > that update is done on (using stored procedures...).
> > 'We can no see that the row has successfully been added to the =
database,
> > 'with a "Identity" (MSSQL) value as PK. Perfect!:
> > dschanges.tables("PriceLists").Rows(0).Item("PriceListID") 1635 =
{Integer}
> > Object
> >
> > Step 3.
> >
> > 'Let me now simply do a "ds.Merge(dsChanges)" and have a new look =
at the
> > values.
> > 'What! - Merge has added a NEW row instead of updating the newly =
created
> > one.
> > ds.Tables("PriceLists").Rows.Count ---> 22 Integer
> >
> > 'The row that was added by me was not touched by the Merge (status =
still
> > "Added") - see:
> > ds.Tables("PriceLists").Rows(20).Rowstate ---> Added
> > System.Data.DataRowState
> > ds.Tables("PriceLists").Rows(20).Item("PriceListID") =
{System.DBNull}
> Object
> >
> > 'But the - NOT WANTED - new row that Merge created has the new PK =
value.
> > ds.Tables("PriceLists").Rows(21).Item("PriceListID") 1635 {Integer}
> Object
> >
> > Merge fails to understand how to merge the newly created row that =
was
> > bounced to data layer and complemented with the "automaticly created
> unique
> > primary key value" (quote from help file above).
> >
> > Can you understand my problem?
> > Working with the combination of "GetChanges" / "Merge" / "MSSQL - =
Identity
> > column" must be a common scenario.
> > The scenario should really work - MS is describing it in the help =
file
> > referred to above ;-)
> >
> > I really hope I am doing something wrong - but what ?
> >
> > Can it be the lack of .PrimaryKey constraint on the DataTable that =
makes
> it
> > impossible for Merge to find the row to update?
> > BUT I can NOT have a .PrimaryKey constraint - as I have understood -
> because
> > the client dataset MUST ALLOW the PriceListID column to be NULL =
until
> > complemented with "Identity generated PK" by data layer.
> >
> > Coding in VisualBasic.
> >
> > Best regards
> > Benjamin Tengelin, Sweden
> >
> >
> >
>=20
>
------=_NextPart_000_000F_01C46441.60F53130
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2800.1400" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY>
<DIV><FONT face=3DArial size=3D2>Hi!</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>I looked at the article: </FONT><A=20
href=3D"http://msdn.microsoft.com/library/default.asp?url=3D/library/en-u=
s/dnadonet/html/manidcrisis.asp"><FONT=20
face=3DArial=20
size=3D2>http://msdn.microsoft.com/library/default.asp?url=3D/library/en-=
us/dnadonet/html/manidcrisis.asp</FONT></A></DIV>
<DIV><FONT face=3DArial size=3D2>and followed it by hooked on PrimaryKey =
and=20
AutoIncrements settings. But...</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>This article is a nice suggestion if =
your are=20
satisfied with the fact that you, after saving, continue (!)&nbsp;to =
work with=20
the client side (!) generated AutoIncrements (-1,-2,-3 ...) until you do =
a fresh=20
reload&nbsp;of the DataSet (e g restarts the&nbsp;form). It </FONT><FONT =

face=3DArial size=3D2>is first when you do a complete DataSet reload =
that you get=20
the real server (!) side AutoIncrements.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>But MSDN documentation "promises"=20
more...</FONT></DIV>
<DIV><A=20
href=3D"http://msdn.microsoft.com/library/default.asp?url=3D/library/en-u=
s/cpref/html/frlrfsystemdatadatasetclassmergetopic2.asp"><FONT=20
face=3DArial=20
size=3D2>http://msdn.microsoft.com/library/default.asp?url=3D/library/en-=
us/cpref/html/frlrfsystemdatadatasetclassmergetopic2.asp</FONT></A></DIV>=

<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>It says (and that is exactly what I =
want to=20
achive):</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2><EM>In a client application, it is =
usual to have a=20
single button that the user can click that gathers the changed data and=20
validates it before sending it back to a middle tier component. In this=20
scenario, the </EM></FONT><A=20
href=3D"http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdat=
adatasetclassgetchangestopic.asp"><FONT=20
face=3DArial size=3D2><EM>GetChanges</EM></FONT></A><FONT face=3DArial =
size=3D2><EM>=20
method is first invoked. That method returns a second DataSet optimized =
for=20
validating and merging. This second DataSet object contains only the=20
</EM></FONT><A=20
href=3D"http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdat=
adatatableclasstopic.asp"><FONT=20
face=3DArial size=3D2><EM>DataTable</EM></FONT></A><FONT face=3DArial =
size=3D2><EM> and=20
</EM></FONT><A=20
href=3D"http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdat=
adatarowclasstopic.asp"><FONT=20
face=3DArial size=3D2><EM>DataRow</EM></FONT></A><FONT face=3DArial =
size=3D2><EM>=20
objects that were changed, resulting in a subset of the original =
DataSet. This=20
subset is generally smaller, and thus more efficiently passed back to a =
middle=20
tier component. The middle tier component will then update the original =
data=20
source with the changes through stored procedures. The middle tier can =
then send=20
back either a new DataSet that includes original data and the latest =
data from=20
the data source (by running the original query again), or it can send =
back the=20
subset with any changes that have been made to it from the data source. =
(For=20
example, if the data source <STRONG>automatically creates unique primary =
key=20
values</STRONG>, these values can be propagated back to the client =
application.)=20
In either case, the returned <STRONG>DataSet can be merged back into the =
client=20
application's original DataSet with the Merge =
method</STRONG>.</EM></FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>This documentation&nbsp;doesn't say =
that you have=20
to do a total reload of the DataSet to get the server =
side&nbsp;generated=20
AutoIncrements.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>The new row should simple be bounced =
down to data=20
layer and the new row in the client dataset should be =
"replaced"/"complemented"=20
by using the <STRONG>.Merge</STRONG>-method.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Not added !!!</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Anyone that has implemented =
the&nbsp;above nice=20
description by Microsoft?</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Best regards<BR>Benjamin Tengelin,=20
Sweden</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>"William Ryan eMVP" &lt;</FONT><A=20
href=3D"mailto:dotnetguru@comcast.nospam.net"><FONT face=3DArial=20
size=3D2>dotnetguru@comcast.nospam.net</FONT></A><FONT face=3DArial =
size=3D2>&gt;=20
wrote in message </FONT><A=20
href=3D"news:ugKb4ICZEHA.2216@TK2MSFTNGP10.phx.gbl"><FONT face=3DArial=20
size=3D2>news:ugKb4ICZEHA.2216@TK2MSFTNGP10.phx.gbl</FONT></A><FONT =
face=3DArial=20
size=3D2>...</FONT></DIV><FONT face=3DArial size=3D2>&gt; Check out Bill =
Vaughn's=20
Managing an @@Identity Crisis at </FONT><A =
href=3D"http://www.betav.com"><FONT=20
face=3DArial size=3D2>www.betav.com</FONT></A><FONT face=3DArial =
size=3D2> -&gt;<BR>&gt;=20
Articles -&gt; MSDN.&