LINQ to SQL, DataGridView a CommitChanges   otázka

VB.NET

Zabývám se teď technologiemi kolem LINQu a narazil jsem na zajímavý problém.

Mějme POCO objekt, vygenerovaný z databáze pomocí toho klikacího udělátka ve Visual studiu, řekněme ZAKAZNIK.

Dále, natáhneme z databáze zákazníky:

Dim MojiZakaznici as ZAKAZNIK = From zak in db.ZAKAZNIK select ZAK

Vrátí, řekněme 5 zákazníků, které nabinduji na BindingSource a toto BindingSource pak použiji jako DataSource pro, řekněme, DataGridView. Toto funguje.

V DataGridView následně provedu, dejme tomu, smazání dvou řádků, tedy dvou zákazníků. V určité době pak provedu SubmitChanges nad příslušným DataContextem a pokusím se dva zákazníky smazat i v databázi.

Jenomže: Díky referenční integritě se první zákazník nesmaže (má třeba objednávky) a celé SubmitChanges skončí na chybě.

Otázky: 1) Lze nějak provést smazání alespoň těch položek, které by prošly?

2) Lze nějak donutit DataContext, aby zapomněl na to, že má nevyřízenou položku v Changesetu a napříště se nepokoušel DELETE provést, protože to zase neprojde? (Obávám se, že nikoli, že jediným řešením je nový datacontext). Elegantní by bylo třeba DataContext.GetChangeset().Deletes.Clear, ale kolekce změn je bohužel jen pro čtení ;-(

3) A konečně - jak elegantně donutit DataGridView, aby řádek, který nelze smazat, znovu zobrazila jako existující?

Ve VB6, kde se používaly gridy třetích stran, toto samozřejmě fungovalo, neboť po smazání řádku se program vždy pokusil provést změnu i v databázi. Nicméně zde se změny "štosují" až do zavolání SubmitChanges.

Neřešili jste něco podobného?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já to řešil následujícím způsobem. Nejdříve pomocí LINQ vytvořte nějaký akční příkaz, třeba smazání určitého řádku v databázi. Ale pak ho neukládejte pomocí db.SubmitChanges ale spustě funkci Serversave. Tato fuknkce buď provede změny v databázi anebo vráti "False". Pak už je jednoduché na základě tohoto vyhodnocení provést příslušné změny v datagridview.

pozn. Ten název akce tam být nemusí, ale mám to tak, abych přímo v aplikaci viděl u jaké operace se případně příkaz neprovedl.

If ServerSave("Nějaký název operace") Then 'nějaké akce třeba smazání řádku v datagridview

Public Function ServerSave(ByVal Název_Akce As String) As Boolean
        
        Try
            db.SubmitChanges(ConflictMode.FailOnFirstConflict)
        Catch ex As ChangeConflictException
            For Each occ As ObjectChangeConflict In db.ChangeConflicts
                occ.Resolve(Data.Linq.RefreshMode.KeepCurrentValues)
            Next
            Try
                db.SubmitChanges(ConflictMode.FailOnFirstConflict)
            Catch ex2 As ChangeConflictException
                MsgBox("Nelze uložit " & Název_Akce, MsgBoxStyle.Critical, "Chyba při ukládání dat")
                Return False
            End Try
                End Try
        Return True

    End Function

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Díky, ale problém je někde jinde. Především (opravte mě někdo, pokud se mýlím) FailOnFirstConflict se týká pouze konfliktů konkurence, nikoli integrity. A potom, přijde mi, že to neřeší ani jeden ze tří problémů výše. I tak díky za pomoc.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já bych si dovolil tvrdit, že to problém řeší. Funkce otestuje zda lze smazat určitý údaj, který třeba kvůli referenční integritě smazat nejde a tak funkce vrátí false a vy žádnou změnu v datagridu neprovedete. Pokud však vrátí True, tak se na serveru změny provedou a vy můžete s klidným svědomím následně smazat či přidat daný řádek v datagridu. Nevím co více by jste si přál, když asi kaskádovitě mazat nemůžete, protože jak jste uvedl máte některá data jen jen pro čtení ?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

omlouvám se, ale neuvedl jste že to nemáte pro čtení ale předpokládám že kaskádovitě mazat nechcete.

Přesto si dovoluji tvrdit, že to řeší všechny tří dotazy které jste podal. Možná existuje nějaký elegantnější způsob vyhodnocení, ale ošetřený test mi zase tak špatný nepřijde. navíc si můžete zjistit, z jakého důvodu nedošlo k odstranění dat, např. právě referenční integrita a podle toho dále řešit tento konflikt.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Bohužel nemáte pravdu. Kdybyste ji měl, bylo by to skutečně řešení mého problému, ale není to tak. Je třeba si nastudovat, co ConflictMode umí a neumí, viz zde: http://msdn.microsoft.com/en-us/library/...

Jinými slovy: Editujeme dva stejný záznam, já změním "a" na "b", zatímco Vy změníte "a" na "c". Vy uložíte první (a bez chyby), já musím řešit FailOnFirstConflict. Na tohle to funguje.

Jiný případ. Jsem sám, kdo s databází pracuje, a změním "a" na "b", přičemž "b" neprojde, dejme tomu, update triggerem. Mě SubmitChanges SELŽE, a pokud v changesetu byly další změny, nemám již šanci je provést. A to je právě ten problém.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback