Newsgroup: it.comp.lang.visual-basic
Titolo: Database e struttura client-server

Salve a tutti,
Dovrei realizzare un gestionale, che possa essere sia uno "normale" che con 
architettura client-server.
Ovvero, il file del database si trova in un computer, e negli altri computer 
della LAN si trovano i vari programmi che accedono tutti a quello stesso 
database.
In questo modo il backup sarŕ centralizzato e ogni programma accederŕ sempre 
ai dati aggiornati.
Alcune domande:
1) Come č meglio fare un architettura del genere? Basta cambiare la 
connection string o mi sfugge qualcosa? Non uso i dataset ma i normali 
SqlConnection.
2) Che succede se due client eseguono nello stesso momento un SqlCommand al 
database?
3) Altre cose da tenere in considerazione?
Uso visual basic 2005 e come database SQL Server 2005 Express.
Grazie a tutti in anticipo,
-- 
Carmine ( 
pikachu...@gmail.com
 (Togli la scritta NOSPAM) )
Webmaster di The Total Site: 
http://www.thetotalsite.it
My Blog: 
http://blog.thetotalsite.it
Gamertag XBOX Live: Carmine XX
http://live.xbox.com/it-IT/profile/profile.aspx?pp=0&GamerTag=Carmine+XX

 SqlCommand al database?
dipende dalle "conseguenze" dei comandi da eseguire... semplici proiezioni 
verranno servite tendenzialmente senza problemi, dove invece queries di 
aggiornamento potrebbero fallire/sovrascrivere aggiornamenti precedenti... 
devi valutare come gestire la concorrenza... puoi utilizzare "prinicipi" 
tradizionali come "last wins", dove l'ultima esecuzione "vince" 
sovrascrivendo eventuali scritture precedenti/concomitanti, ma questo spesso 
non e' molto gradito dagli utenti, che solitamente desiderano essere 
informati di accadimenti relativi all'esecuzione dei propri aggiornamenti...
personalmente ti consiglierei di aggiungere una colonna di tipo timestamp 
(rowversion), che viene automaticamente modificata dal sistema ad ogni 
aggiornamento, e risulta quindi semplice identificare fallimenti, nelle 
operazioni DML..
ti basta in effetti verificare il @@ROWCOUNT determinato da operazioni quali
UPDATE customers
    SET ..... = @nuovo_valore
    WHERE customer_code = @pk_value
        AND [RowVersion] = @OldRowVersionValue;
un @@ROWCOUNT = 0 indica che non e' stata aggiornata alcuna riga, vuoi 
perche' essa non sia piu' presente nella base dati, oppure che non esista 
piu' alcuna riga che soddisfi il filtro impostato anche tramite il valore di 
[RowVersion] (che nel frattempo e' cambiato se la riga e' stata modificata 
da altri)..
potrai poi procedere come meglio credi, forzando comunque l'aggiornamento 
ovvero informare l'utente in attesa di sue decisioni in merito...
questo modo di "lock" e' abbastanza leggero, nel senso che solitamente 
coinvolge solo l'utilizzo della chiave primaria e, chiaramente, della 
colonna di rowversion, dove invece altre modalita' di verifica richiedono un 
confronto su "tutte" le colonne dell'entita' onde non sovrascrivere il 
lavoro altrui..
tipicamente la modifica diventa
UPDATE customers
    SET col1 = @nuovo_valore,
            .......
    WHERE customer_code = @pk_value
        AND col1 = @vecchio_valore_col1
        ....
        AND coln = @vecchio_valore_coln;
quindi richiedendo 2 x num_colonne parametri invece di num_colonne (incluso 
[RowVersion])
sara' anche tua necessita' ritornare al chiamante, solitamente tramite il 
parametro stesso di @RowVersion il nuovo valore in OUTPUT...
quindi
CREATE PROCEDURE dbo.usp_Aggiorna_Customer (
    @Id int ,
    @Nome varchar (n) ,
    .....,
    @RowVersion timestamp OUTPUT
    )
AS BEGIN
    DECLARE @r int;
    SET NOCOUNT OFF;
    BEGIN TRY
        UPDATE dbo.customers
            SET Nome = @Nome
            WHERE Id = @Id
                AND [RowVersion] = @RowVersion;
        SET @r = @@ROWCOUNT;
        IF (@r = 0) BEGIN
            DECLARE @msg varchar(200);
           -- in caso di non aggiornamento righe notifica la
           -- possibile violazione di concorreza e necessita di refresh
           SET @msg = 'Impossibile modificare riga con Id = [%d] in  [%s].' 
+ CHAR(10) + 'Possibile conflitto di concorrenza.';
            RAISERROR (@msg, 16, 1, @Id , 'tabella Customers');
            END;
          -- ritorna il timestamp in output
        SELECT @RowVersion = [RowVersion]
            FROM dbo.customers
            WHERE [Id] = @Id;
          RETURN 0;
     END TRY
     BEGIN CATCH
        -- ritorna l'errore
        DECLARE @ErrorMSG varchar(2000);
        SET @ErrorMSG = ERROR_MESSAGE()
        RAISERROR (@ErrorMSG, 16, 1);
        RETURN -100
    END CATCH
END;
saluti
-- 
Andrea Montanari (Microsoft MVP - SQL Server)
http://www.asql.biz
 
http://italy.mvps.org
DbaMgr2k ver 0.21.0 - DbaMgr ver 0.65.0 and further SQL Tools
--------- remove DMO to reply