Citat:
i_nenad: Covek je lepo napisao sintaxu , koju koristi:
dataadapter.update(ds.getchanges())
predpostavljam da koristi generisane comande dataadaptera, a ne stored procedure.
...
znaci jedno resenje je :
dataadapter.update(ds), ako broj slogova koje imas u tebeli nije veliki ili , merge koji sam dao u prvom reply-ju.
Pozdrav
Hmm, ajd da probam da obrazlozim zasto ovo ne valja.
1. Cak i kad se automatski generisu komande kao sto pretpostavljas, i dalje je po defaultu ukljucena opcija "Refresh dataset", koja ce napraviti SQL komandu sa sledecim CommandText-om:
Code:
UPDATE ImportBatch SET UserId = @UserId, CreatedOn = @CreatedOn WHERE (ImportBatchId = @Original_ImportBatchId);
SELECT ImportBatchId, UserId, CreatedOn FROM ImportBatch WHERE (ImportBatchId = @ImportBatchId)
sto se svodi na stored proceduru koju sam napisao gore. Ako nema SELECT u komandi, ne postoji automaski nacin da se osvezi dataset sa generisanim vrednostima. To je prvo sto mora da se proveri, bez toga je ostatak ovog topica nevazan.
2. ds.GetChanges proizvede
kopije redova koji su dodati/promenjeni/obrisani. Ti redovi vise nemaju nikakve veze sa originalnim redovima. Kad se ovaj dataset posalje adapteru ti "novi" redovi dobiju nove IDove ili ostanu isti (ako nema SELECT dela iz tacke 1.), nazovimo ovaj dataset DSCH
3. Kad radis Merge, jedini nacin da dataset zakljuci koji redovi su novi a koji izmenjeni je PrimaryKey. I sad se javljaju dve opcije (od kojih nijedna ne valja):
3.1 (bez SELECTA u komandi): ID polje je ostalo isto, dataset ce ostale vredosti u redu zameniti sa onima iz DSCH, tj, nece uraditi nista posto dataadapter nije menjao DSCH jer se iz komande/stored procedure nije nista vratilo.
3.2 (sa SELECT): ID polje ce dobiti novu realnu vrednost u DSCH. ds ce pretraziti svoj primary key i videce da ne postoji red sa tim ID-om i zakljucice da je taj red iz DSCH ustvari NOVI RED i dodace ga umesto da stari zameni novim. Kao posledica ovoga svi dodati redovi u ds ce se duplirati samo sa drugim ID-ovima. Dalje, svi redovi koji su bili iskopirani sa GetChanges ce i dalje ostati u statusu "Added" i ako ponovo pozoves GetChanges,Update bice ponovo dodati u bazu.
Bottom line, ne postoji razlog da se koristi
dataadapter.update(ds.getchanges()) sem kad se dataset salje preko webservisa ili u remoting pa da se smanji pritisak na bandwitdh (a u tom slucaju posle svakog merge-a mora da se radi ciscenje duplikata).
U WinForms je UVEK bolje koristiti
dataadapter.update(ds), posto ce dataadapter pre poziva komandi uraditi pretrazivanje dataset-a isto kao sto ce to uraditi ds.GetChanges() samo sto ce:
a) biti brze, posto nece praviti kopije redova
b) biti efikasnije, posto ce SELECT u komandi automatski promeniti red u originalnom datasetu te nema potrebe za merge-om.
Broj redova nema veze sa ovim, ako ukupno ima milion redova u datasetu, i dataadapter i ds.GetChanges moraju da prodju kroz isti proces da bi odredili koji treba da se posalju bazi (tj koji treba da se iskopiraju u DSCH).
PS. Sad vidim da nisam eksplicitno naveo da uz moj primer mora da se koristi dataadapter.update(ds), izvinjavam se za tu omasku.
PS> Ako mi i dalje ne verujes probaj sledeci kod (dataset je zakacen za poruku):
Code:
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
DatasetX dsx = new DatasetX();
dsx.tabela.AddtabelaRow("novi red 1");
dsx.tabela.AddtabelaRow("novi red 2");
Console.WriteLine("Pre getchanges/update/merge");
PrintTable(dsx.tabela);
DatasetX dsch = (DatasetX)dsx.GetChanges();
SimulateDataAdapter(dsch, 25);
dsx.Merge(dsch);
Console.WriteLine("Post merge");
PrintTable(dsx.tabela);
dsch = (DatasetX)dsx.GetChanges();
SimulateDataAdapter(dsch, 35);
dsx.Merge(dsch);
Console.WriteLine("Post second merge");
PrintTable(dsx.tabela);
Console.ReadLine();
}
static void PrintTable(DatasetX.tabelaDataTable tbl)
{
foreach (DatasetX.tabelaRow _row in tbl.Rows)
{
Console.Write("{0,3} : {1}\n", _row.ID, _row.polje);
}
}
static void SimulateDataAdapter(DatasetX dsch, int start)
{
int xx = start; // recimo da je start prvi sledeci slobodni u bazi
foreach (DatasetX.tabelaRow _row in dsch.tabela.Rows)
{
_row.ID = xx++;
}
dsch.AcceptChanges();
}
}
ovo je izlaz koji ces dobiti:
Code:
Pre getchanges/update/merge
-1 : novi red 1
-2 : novi red 2
Post merge
-1 : novi red 1
-2 : novi red 2
25 : novi red 1
26 : novi red 2
Post second merge
-1 : novi red 1
-2 : novi red 2
25 : novi red 1
26 : novi red 2
35 : novi red 1
36 : novi red 2
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić