Podobné hlášky mě už taky párkrát pronásledovaly. Já používám netypový dataset a pracuji přímo s objekty SQLDataAdapter (mám DB MSSQL), ale princip bude obdobný i u Vašeho typového datasetu s objekty TableAdapter. Synchronizace dat v objektu DataTable s podkladovou databází se děje prostřednictvím datového adaptéru, který musí mít inicializovány vlastnosti SelectCommand (pro metodu Fill, která tahá data z DB do datasetu) InsertCommand, UpdateCommand a DeleteCommand. V objektu DataTable (který je u Vás přes BindingSource svázán s ovládacím prvkem (zřejmě DataGridView)) se udržuje informace o stavu každého řádku ve vlastnosti RowState. Po načtení dat metodou Fill má každý řádek stav "Unchanged". Pokud do mřížky (a tím automaticky i do DataTable) přidáte řádek, bude mít stav "Added", pokud řádek smažete z mřížky, v objektu Datatable zůstane a bude mít status Deleted, pokud změníte hodnotu v jakékoli buňce, bude mít řádek status "Modified". Jakmile zavoláte metodu Update datového adapteru, projdou se všechny řádky příslušného objektu DataTable a pro ty, které mají status Added se provede nad databází příkaz, definovaný ve vlastnosti InsertCommand, obdobně DeleteCommand pro smazané řádky a UpdateCommand pro změněné řádky. Vámi zmiňovaná hláška obecně znamená, že některý ze SQL příkazů nenašel v podkladové databázi řádek, který by vyhovoval WHERE podmínce. U DeleteCommandu to bývá typicky tehdy, když mažete řádek, který už mezitím smazal někdo jiný. U UpdateCommandu to může být způsobeno buď primárním klíčem, nebo složitostí WHERE podmínky v příkazu, který vygeneroval designer či CommandBuilder. Nevím, jak vytváříte primární klíče u nově přidávaných záznamů, zda máte v podkladové DB primární klíč s autoincrementem apod. Často se doporučuje, používat v podkladové DB PK sloupec typu integer s autoincrementem od 1 do kladných hodnot a v datasetu si nastavit u odpovídajícího sloupce autoincrement do záporných hodnot. V InsertCommandu pak tento PK neuvádět s tím, že podkladová DB si jej přiřadí sama. Pokud ale nezavoláte obratem metodu Fill či nepoužijete u UpdateCommandu se vším všudy možnost ovlivnit zpětně právě zpracovávaný objekt DataRow a tím změnit provizorní záporné ID na to skutečné z podkladové DB, pak máte v Datatable řádek s primárním klíčem, který není v DB a tím pádem při následné případné úpravě hodnoty v daném řádku dostanete přesně Vámi uváděnou hlášku. Navrhuju prověřit manipulaci s primárním klíčem, odchytit si událost RowUpdated datového adaptéru, která se volá po každém jednotlivém příkazu (a dá se zde i vyhodnotit typ chyby a případně nechat program pokračovat), zkontrolovat, jak přesně vypadá vlastní UpdateCommand resp. hlavně jeho WHERE podmínka) a též nesynchronizovat DB při změně v každé buňce, ale třeba až po opuštění řádku (třeba v události RowValidated a testnout si vlastnost IsCurrentRowDirty) Při použití MSSQL jsou pro primární klíče výhodné sloupce typu uniqueidentifier, které se dají vygenerovat jak na straně serveru, tak v programu a mohou tedy být součástí InsertCommadu.
|