In un gestionale l’utente vuole avere la possibilità di eseguire diverse operazioni (inserimento/modifica/eliminazione) e, successivamente, annullare o confermare in un unico passo le operazioni fatte. Per questioni di semplicità ho creato un database “Anagrafica” contenente una sola tabella.
Di seguito viene mostrato lo script per la creazione della tabella:
USE [Anagrafica]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Anagrafica](
[Id] [uniqueidentifier] ROWGUIDCOL
NOT NULL CONSTRAINT [DF_Anagrafica_Id] DEFAULT (newid()),
[Nome] [nvarchar](max) NOT NULL,
[Cognome] [nvarchar](max) NOT NULL,
[Indirizzo] [nvarchar](max) NOT NULL,
[Citta] [nvarchar](max) NOT NULL,
[Cap] [nchar](5) NOT NULL,
[Provincia] [nchar](2) NOT NULL,
CONSTRAINT [PK_Anagrafica] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
Il dataLayer del gestionale è stato realizzato Linq2SQL ed i dati vengono visualizzati utilizzando un dataGridView (vedi foto)

Il problema nella gestione dei dati.
I dati vengono visualizzati nel DataGridView assegnando al suo dataSource un Oggetto Table<Anagrafica> (vedi codice)
dcAnagraficaDataContext dc = new dcAnagraficaDataContext();
dataGridView1.DataSource = dc.GetTable<Anagrafica>();
Una volta che sono stati visualizzati i dati l’utente ha la possibilità di modificare i dati visualizzati nel dataGridView, il mio problema a questo punto è capire quali sono le righe del dataGridView che sono state modificate e qual’è il loro stato, il dataContext contiene un metodo “GetChangeSet()” che restituisce una collection contenente le righe modificate del dataGridView; a questo punto i dati vengono salvati sul database (vedi codice)
1: private void SaveChanges()
2: {
3: try
4: {
5: //dcdi tipo dcAnagraficaDataContex
6: ChangeSet cs = dc.GetChangeSet();
7: dc.Connection.Open();
8: dc.Transaction = dc.Connection.BeginTransaction();
9: for (int i = 0; i < cs.Inserts.Count; i++)
10: { ((Anagrafica)cs.Inserts).Id = Guid.NewGuid(); }
11: dc.SubmitChanges();
12: dc.Transaction.Commit();
13: }
14: catch (Exception ex)
15: {
16: dc.Transaction.Rollback();
17: throw ex;
18: }
19: finally
20: {
21: if (dc.Connection.State == ConnectionState.Open)
22: { dc.Connection.Close(); }
23: dataGridView1.Refresh();
24: }
25: }
Nel caso in cui l’utente vuole annullare le modifiche fatte anche in questo caso si lavora con la collection ChangeSet, con la differenza che vengono invertite le operazioni rappresentate dalle liste presenti nella collection (vedi codice).
1: private void RevertChanges()
2: {
3: try
4: {
5: //dc di tipo dcAnagraficaDataContext
6: ChangeSet cs = dc.GetChangeSet();
7: dc.Connection.Open();
8: dc.Transaction = dc.Connection.BeginTransaction();
9: for (int i = 0; i < cs.Inserts.Count; i++)
10: {
11: var temp = cs.Inserts.GetType();
12: dc.GetTable(temp).DeleteOnSubmit(cs.Inserts);
13: }
14: for (int i = 0; i < cs.Updates.Count; i++)
15: {
16: var temp = cs.Updates.GetType();
17: ModifiedMemberInfo[] modifyInfo =
dc.GetTable(temp).
GetModifiedMembers(cs.Updates);
18: for (int j = 0; j < modifyInfo.Length; j++)
19: {
20: if (modifyInfo[j].Member is PropertyInfo)
21: {
22: var pi = (PropertyInfo)modifyInfo[j].Member;
23: pi.SetValue(cs.Updates,
modifyInfo[j].OriginalValue,
null);
24: }
25: if (modifyInfo[j].Member is FieldInfo)
26: {
27: var fi = (FieldInfo)modifyInfo[j].Member;
28: fi.SetValue(cs.Updates,
modifyInfo[j].OriginalValue);
29: }
30: }
31: }
32: for (int i = 0; i < cs.Deletes.Count; i++)
33: {
34: var temp = cs.Deletes.GetType();
35: dc.GetTable(temp).InsertOnSubmit(cs.Deletes);
36: }
37: dc.SubmitChanges();
38: dc.Transaction.Commit();
39: }
40: catch (Exception ex)
41: {
42: dc.Transaction.Rollback();
43: throw ex;
44: }
45: finally
46: {
47: if (dc.Connection.State == ConnectionState.Open)
48: { dc.Connection.Close(); }
49: dataGridView1.Refresh();
50: }
51: }
Sia la procedura “SaveChanges()” che la procedura “RevertChanges()” utilizzano le transazioni. In particolare la procedura “RevertChanges()” funziona attraverso l’utilizzo della reflection.