PDA

View Full Version : [C#] DAL/CRUD


RaouL_BennetH
06-11-2008, 15:05
....

seguendo i suggerimenti di parecchi di voi... mi sono deciso a documentarmi in merito a questi argomenti.

Ho subito trovato un ottimo tutorial con relativo esempio che serve per poter gestire tutte le varie operazioni su database a prescindere dal tipo di provider.

Il link è :

http://www.dotnetjohn.com/articles.aspx?articleid=244

Leggendo la guida fino in fondo e adattando il sorgente ai miei scopi, sono riuscito ad ottenere la dll che mi permette di collegarmi a qualsiasi db senza sforzo. Quanto sia didattica e utile la guida, se è buon codice oppure no, sinceramente non sono in grado di stabilirlo.

Bene...andiamo avanti

Adesso, mi manca un altro pezzo del puzzle:

generalmente le applicazioni sulle quali mi diletto sono di tipo windows forms.
Stanco e nauseato di inserire nei vari bottoni cose come:



private void buttonSalva_Click(object sender, EventArgs e)
{
try
{
DataBase d = new DataBase();
d.Open();
d.Insert(text1.text, et....);
}


ma sopratutto stanco del fatto che se mi cambia l'interfaccia grafica devo praticamente riscrivere quasi tutto.. volevo fare l'ulteriore salto di qualità gestendo quello che in gergo viene chiamato CRUD.

Bene.. ho quindi proceduto in questa maniera:

creato un nuovo progetto di tipo Class Library

Ho aggiunto un dataset per ricrearmi lo schema delle tabelle che mi interessano ricreando le colonne e le varie relazioni.

Arrivo al punto..:

Non ho idea di come usare questo dataset!
Non riesco a trovare documentazione tranne quelle che sono fatte per chi certi argomenti già li conosce.

La mia idea era quella di avere una libreria indipendente dal tipo di interfaccia che poi andrò a sviluppare.

Plz.. chi mi da una mano? :help:

Grazie mille.

RaouL.

RaouL_BennetH
07-11-2008, 17:54
uppettino....

RaouL_BennetH
09-11-2008, 10:24
:help:

tomminno
09-11-2008, 11:32
creato un nuovo progetto di tipo Class Library

Ho aggiunto un dataset per ricrearmi lo schema delle tabelle che mi interessano ricreando le colonne e le varie relazioni.


Dataset? Scusa con che versione del linguaggio stai lavorando?
I Dataset avevano senso solo nella versione 1.1, dalla 2.0 in poi rappresentano un antipattern. Non consentono una programmazione ad oggetti (non puoi applicare l'ereditarietà ai dataset), se non tipizzati sono delle scatole nere, il che significa che chi li usa ai livelli più alti deve andare a spulciare la query sottostante per capire quali campi ci sono dentro e magari il db per capirne il tipo. Insomma un retaggio del passato assolutamente da evitare oggi.


La mia idea era quella di avere una libreria indipendente dal tipo di interfaccia che poi andrò a sviluppare.

Plz.. chi mi da una mano? :help:

Grazie mille.

RaouL.

Nella libreria puoi mettere le primitive di accesso al db, ma ti ci vuole comunque uno strato di accesso ai dati nell'applicativo che vai a sviluppare che utilizzi le primitive adattandole al caso.

Poi una osservazione sul codice che hai preso ad esempio: Sul dispose chiama semplicemente il close e non il dispose della connessione (e solo se la connessione è Open, ad esempio se lo stato fosse Fetching la connessione rimane allegramente aperta), inoltre la gestione manuale dei close è a rischio, una qualunque eccezione che faccia uscire gli oggetti dallo scope causa la mancata chiusura degli oggetti istanziati.

[EDIT] Non avevo visto: manca l'implementazione del Finalize

RaouL_BennetH
09-11-2008, 15:44
grazie Tomminno.

Avresti quindi qualche suggerimento da darmi ?

che so... esempi, link, schemi...

Grazie mille.

RaouL.

RaouL_BennetH
10-11-2008, 09:09
Buondì :)

Ho lasciato perdere il dataset e sto procedendo in quest'altra direzione:

In una libreria separata, sto ricreando lo schema del database:



//Classe Business Object Anagrafica
public class BOAnagrafica
{
private int id;
private string cognome;
private string nome;
private DateTime dataNascita;
private string gender;
//blabla
private DALAnagrafica dAnagrafica;

public int ID
{
get { return id; }
set { id = value; }
}

public string Cognome
{
get { return cognome; }
set { cognome = value; }
}

//blabla per gli altri campi





//Data Access Layer per Anagrafica
public class DALAnagrafica
{
//da implementare
}



Posso andare avanti secondo voi o sto perdendo ancora del tempo prezioso?

Grazie mille :)

RaouL.

Einstein
10-11-2008, 12:27
Anche a me i Dataset non piacciono granché, ma considerarli un antipattern mi sembra esagerato.
I Dataset, per applicazioni semplici, dicono ancora la loro: vuoi per la facilità di creazione, vuoi per l'ottimo supporto che fornisce Visual Studio, vuoi per l'ottimo supporto al binding.
Quindi non mi sento di escluderli a priori, ma solo dopo una valutazione di quello che devo fare.
Per quanto riguarda il tuo secondo approccio, toglierei il riferimento al Data Layer dalle classi che rappresentano le tue entities, quindi:


public class DALAnagrafica
{
public int Insert(BOAnagrafica anagrafica)
{
// codice per inserire la entity sul db
}

public int Update(BOAnagrafica anagrafica)
{
// codice per aggiornare la entity
}
}


Se vuoi mantenere il codice di persistenza all'interno della entity, puoi usare il pattern Active Record (http://martinfowler.com/eaaCatalog/activeRecord.html), per avere una cosa simile:


public class BOAnagrafica
{
// implementazione di membri e proprietà pubbliche

public int Insert()
{
// codice per inserire la entity.
}

public int Update()
{
// codice per aggiornare la entity
}
}


Non è mia intenzione metterti confusione, te l'assicuro :)
Voglio solo metterti davanti un po' di soluzioni, e nessuna di queste è necessariamente meglio dell'altra: dipende sempre dal tuo contesto applicativo.

tomminno
10-11-2008, 13:50
Anche a me i Dataset non piacciono granché, ma considerarli un antipattern mi sembra esagerato.


Già solo il fatto di non poter programmare ad oggetti se c'è di mezzo un dataset basta a definirli come antipattern.
Ripeto avevano un senso quando ancora non c'era il supporto ai generics (ovvero nella versione beta del .NET qual era la 1.1)


I Dataset, per applicazioni semplici, dicono ancora la loro: vuoi per la facilità di creazione, vuoi per l'ottimo supporto che fornisce Visual Studio, vuoi per l'ottimo supporto al binding.


Parli per caso della "facilità" con cui puoi creare un dataset tipizzato da VS2005 in poi? Credo ci vogliano 5 minuti per crearne uno contro i pochi secondi della versione 2003.


Quindi non mi sento di escluderli a priori, ma solo dopo una valutazione di quello che devo fare.


Oggi c'è LINQ (solo per SQLServer per ora) e a salire Entity Framework e NHibernate, che è decisamente complicato da usare.
Ad oggi un DAL scritto a mano che utilizza delle classi contenitore (solo get e set) è la soluzione da adottare nei casi semplici.

Einstein
10-11-2008, 14:17
Oggi c'è LINQ
e domani potrebbe non esserci più...
http://blogs.msdn.com/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx
e a salire Entity Framework
Che attualmente non mi sembra 'sta gran cosa.
e NHibernate, che è decisamente complicato da usare.
Infatti ha una curva di apprendimento piuttosto ripida
Ad oggi un DAL scritto a mano che utilizza delle classi contenitore (solo get e set) è la soluzione da adottare nei casi semplici.

A patto che la tua applicazione non abbia requisiti del tipo "Puoi usare .NET 2.0 e basta" (e ti assicuro che l'ho sentita). In questo caso o ti scrivi un O/RM tu, oppure il Dataset diventa una "gran bella cosa". :)
Anch'io preferisco l'approccio OOP ai dati (i datasets li tengo sempre come ultima opzione), ma quello che voglio dire è che ciascuna decisione architetturale va fatta in base al contesto dell'applicazione e ai requisiti, oltre che ai tempi di sviluppo che si hanno a disposizione.

tomminno
10-11-2008, 14:33
e domani potrebbe non esserci più...
http://blogs.msdn.com/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx


LINQ to Entities è parte dell'entity framework è qualcosa di diverso da LINQ to SQL.


Che attualmente non mi sembra 'sta gran cosa.


E' il primo ORM targato Microsoft. Il che significa completamente integrato nell'IDE, niente più lotte con file XML o con le pessime prestazioni della reflection di NHibernate.


Infatti ha una curva di apprendimento piuttosto ripida


Era, fino al .NET 3.5 SP1, l'unico ORM disponibile per .NET


A patto che la tua applicazione non abbia requisiti del tipo "Puoi usare .NET 2.0 e basta" (e ti assicuro che l'ho sentita). In questo caso o ti scrivi un O/RM tu, oppure il Dataset diventa una "gran bella cosa". :)


Il 2.0 basta e avanza per usare i generics e un DAL scritto a mano nei casi semplici, nei casi complessi c'è NHibernate. Perchè in uno scenario complesso usare i Dataset rende il codice poco manutenibile e comporta scelte di design ben precise.


Anch'io preferisco l'approccio OOP ai dati (i datasets li tengo sempre come ultima opzione), ma quello che voglio dire è che ciascuna decisione architetturale va fatta in base al contesto dell'applicazione e ai requisiti, oltre che ai tempi di sviluppo che si hanno a disposizione.

Si può sempre scegliere di scrivere tutto il codice nel Main o nel Page_Load, non significa che sia una pratica raccomandata.

RaouL_BennetH
10-11-2008, 17:41
Ragazzi, a scanso di equivoci vi dico che al momento posso utilizzare solo il framework 2.0

Inoltre, ciò che sto cercando di fare non è un programma professionale.

A scopo didattico stavo cercando di slegarmi da quelle che erano le mie pratiche abituali di inserire tutto il codice relativo alla gestione del db all'interno dei forms.

eppoi... sto cercando per la prima volta di fare qualcosa di veramente OOP.

Entro domani dovrei aver terminato la prima parte del progetto.

Se non vi secca, gradirei davvero la possibilità che voi possiate dargli uno sguardo e suggerirmi tutto ciò che può essere migliorato.

Ho tanta voglia di crescere ma mi rendo conto che l'argomento è così vasto da non poter essere esaurito all'interno di un 3d.

Nel frattempo..: grazie mille a entrambi :)

RaouL.

banryu79
10-11-2008, 18:21
Iscritto! Mi interessa molto questo thread, tienici aggiornati se puoi :)

Kralizek
10-11-2008, 22:02
Ragazzi, a scanso di equivoci vi dico che al momento posso utilizzare solo il framework 2.0

Inoltre, ciò che sto cercando di fare non è un programma professionale.

A scopo didattico stavo cercando di slegarmi da quelle che erano le mie pratiche abituali di inserire tutto il codice relativo alla gestione del db all'interno dei forms.

eppoi... sto cercando per la prima volta di fare qualcosa di veramente OOP.

Entro domani dovrei aver terminato la prima parte del progetto.

Se non vi secca, gradirei davvero la possibilità che voi possiate dargli uno sguardo e suggerirmi tutto ciò che può essere migliorato.

Ho tanta voglia di crescere ma mi rendo conto che l'argomento è così vasto da non poter essere esaurito all'interno di un 3d.

Nel frattempo..: grazie mille a entrambi :)

RaouL.

La mia è...

fatti le tue classi di Business Logic, fatti un'interfaccia "IDataBound" o qualcosa del genere e decoraci le classi che devono essere salvate su DB
questa interfaccia deve avere i 4 metodi CRUD. (ho usato decoraci perchè noi abbiamo scelto di usare un attributo, tecnica specifica di .net, ma didatticamente non ti serve ed è scocciante da maneggiare)

A questo punto puoi scegliere di farti una classe Factory che si occupa di invocare i metodi crud e amen. Oppure, ma è più sporco, lasci i metodi invocabili sull'oggetto/classe.

Infine è consigliabile crearti una collezione per ogni oggetto di BL.


public class Person {}

public class PersonCollection : List<Person> {}


cui eventualmente puoi creare un costruttore che recupera tutte le righe e, tramite la factory mappa un DataRow sull'oggetto.

RaouL_BennetH
11-11-2008, 12:09
Eccomi :)

Allora, facendo il punto della situazione, il progetto attualmente è diviso in 3 parti:

1) Un Layer che si occupa di capire il tipo di provider sottostante e che gestisce comandi, transazioni, datareader & Co. Il Layer è quello preso dal link del primo post con qualche modifica per renderlo per il sottoscritto più elastico.

2) Un Layer che si occupa invece di definire le entità del database

3) L'interfaccia grafica.

Il punto sul quale sto cercando di approfondire e andare a vanti è il 2°.

Vi posto 2 classi:

1) Quella che definisce la tabella
2) quella che si occupa delle operazioni sul db



//BOAnagrafica.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace AnagraficaLayer
{
public class BOAnagDip
{
private int id_dipendente;
private string cognome;
private string nome;
private string sesso;
private DateTime dataNascita;
private string comuneNascita;
private string provNascita;
private string stato;
private string codiceFiscale;
private string comuneResidenza;
private string provResidenza;
private string indirizzo;
private string cap;
private string telefono;
private string cellulare;
private string email;
private bool isActive;




public int ID_Dipendente
{
get { return id_dipendente; }
set { id_dipendente = value; }
}

public string Cognome
{
get { return cognome; }
set { cognome = value; }
}

public string Nome
{
get { return nome; }
set { nome = value; }
}

public string Sesso
{
get { return sesso; }
set { sesso = value; }
}

public DateTime DataNascita
{
get { return dataNascita; }
set { dataNascita = value; }
}


public string ComuneNascita
{
get { return comuneNascita; }
set { comuneNascita = value; }
}

public string ProvNascita
{
get { return provNascita; }
set { provNascita = value; }
}

public string Stato
{
get { return stato; }
set { stato = value; }
}

public string CodiceFiscale
{
get { return codiceFiscale; }
set { codiceFiscale = value; }
}

public string ComuneResidenza
{
get { return comuneResidenza; }
set { comuneResidenza = value; }
}

public string ProvResidenza
{
get { return provResidenza; }
set { provResidenza = value; }
}

public string Indirizzo
{
get { return indirizzo; }
set { indirizzo = value; }
}

public string Cap
{
get { return cap; }
set { cap = value; }
}

public string Telefono
{
get { return telefono; }
set { telefono = value; }
}

public string Cellulare
{
get { return cellulare; }
set { cellulare = value; }
}

public string Email
{
get { return email; }
set { email = value; }
}

public bool IsActive
{
get { return isActive; }
set { isActive = value; }
}

}
}




//DALAnagrafica.cs
using System;
using System.Collections.Generic;
using System.Data;
using DalTemplate;
using System.Text;

namespace AnagraficaLayer
{
public class DAnagDip
{



private const string insertAnagrafica = "INSERT INTO anagdip " +
"(cognome, nome, sesso, datanascita, comunenascita, provnascita, " +
"stato, codicefiscale, comuneresidenza, provresidenza, indirizzo, " +
"cap, telefono, cellulare, email, isactive) " +
"VALUES " +
"(@cognome, @nome, @sesso, @dataNascita, @comuneNascita, @provNascita, " +
"@stato, @codiceFiscale, @comuneResidenza, @provResidenza, @indirizzo, " +
"@cap, @telefono, @cellulare, @email, @isactive) ";

private const string updateAnagrafica = "UPDATE anagdip " +
"SET cognome = @cognome, nome = @nome, sesso = @sesso, " +
"datanascita = @dataNascita, comunenascita = @comuneNascita, " +
"provnascita = @provNascita, stato = @stato, codicefiscale = @codiceFiscale, " +
"comuneResidenza = @comuneResidenza, provresidenza = @provResidenza, " +
"indirizzo = @indirizzo, cap = @cap, telefono = @telefono, " +
"cellulare = @cellulare, email = @email " +
"WHERE " +
"id_dipendente = @id_dipendente " +
"AND " +
"isactive = @isactive";

private const string deleteLogical = "UPDATE anagdip " +
"SET isactive = @isactive WHERE id_dipendente = @id_dipendente ";

private const string deleteFisical = "DELETE FROM anagdip " +
"WHERE id_dipendente = @id_dipendente ";

cognome";




public DAnagDip()
{

}

public void Add(BOAnagDip b)
{
IDBManager db = new DBManager(DataProvider.PostgreSql, ConnString.ConnectionString);
try
{

db.Open();
db.CreateParameters(16);
db.AddParameters(0, "@cognome", b.Cognome);
db.AddParameters(1, "@nome", b.Nome);
db.AddParameters(2, "@sesso", b.Sesso);
db.AddParameters(3, "@dataNascita", b.DataNascita);
db.AddParameters(4, "@comuneNascita", b.ComuneNascita);
db.AddParameters(5, "@provNascita", b.ProvNascita);
db.AddParameters(6, "@stato", b.Stato);
db.AddParameters(7, "@codiceFiscale", b.CodiceFiscale);
db.AddParameters(8, "@comuneResidenza", b.ComuneResidenza);
db.AddParameters(9, "@provResidenza", b.ProvResidenza);
db.AddParameters(10, "@indirizzo", b.Indirizzo);
db.AddParameters(11, "@cap", b.Cap);
db.AddParameters(12, "@telefono", b.Telefono);
db.AddParameters(13, "@cellulare", b.Cellulare);
db.AddParameters(14, "@email", b.Email);
db.AddParameters(15, "@isActive", b.IsActive);
db.ExecuteNonQuery(CommandType.Text, insertAnagrafica);


}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
}
finally
{
db.Dispose();
}
}

public void Update(BOAnagDip b)
{
IDBManager db = new DBManager(DataProvider.PostgreSql, ConnString.ConnectionString);
try
{
db.Open();
db.CreateParameters(17);
db.AddParameters(0, "@id_dipendente", b.ID_Dipendente);
db.AddParameters(1, "@cognome", b.Cognome);
db.AddParameters(2, "@nome", b.Nome);
db.AddParameters(3, "@sesso", b.Sesso);
db.AddParameters(4, "@dataNascita", b.DataNascita);
db.AddParameters(5, "@comuneNascita", b.ComuneNascita);
db.AddParameters(6, "@provNascita", b.ProvNascita);
db.AddParameters(7, "@stato", b.Stato);
db.AddParameters(8, "@codiceFiscale", b.CodiceFiscale);
db.AddParameters(9, "@comuneResidenza", b.ComuneResidenza);
db.AddParameters(10, "@provResidenza", b.ProvResidenza);
db.AddParameters(11, "@indirizzo", b.Indirizzo);
db.AddParameters(12, "@cap", b.Cap);
db.AddParameters(13, "@telefono", b.Telefono);
db.AddParameters(14, "@cellulare", b.Cellulare);
db.AddParameters(15, "@email", b.Email);
db.AddParameters(16, "@isActive", b.IsActive);
db.ExecuteNonQuery(CommandType.Text, updateAnagrafica);
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
}
finally
{
db.Dispose();
}
}

public void DeleteLogical(BOAnagDip b)
{
IDBManager db = new DBManager(DataProvider.PostgreSql, ConnString.ConnectionString);
try
{
db.Open();
db.CreateParameters(2);
db.AddParameters(0, "@id_dipendente", b.ID_Dipendente);
db.AddParameters(1, "@isactive", b.IsActive);
db.ExecuteNonQuery(CommandType.Text, deleteLogical);
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
}
finally
{
db.Dispose();
}
}





}
}





//dal form poi, mi basta semplicemente chiamare Add() e per la prima volta anche se cambio layout grafico non devo toccare nulla.


Per il mio livello, probabilmente sarà tutto sbagliato, ma la cosa che a me non piace è di dover inizializzare ogni volta quei parametri. Intuisco che ci sia una ripetizione inutile nel codice.

Inutile dirvi che accetto qualsiasi tipo di suggerimento, critica o qualsiasi altra cosa che possa farmi crescere.

Grazie mille :)

RaouL.

tomminno
11-11-2008, 13:18
Per il mio livello, probabilmente sarà tutto sbagliato, ma la cosa che a me non piace è di dover inizializzare ogni volta quei parametri. Intuisco che ci sia una ripetizione inutile nel codice.


Basta che fai un metodo privato che data la classe BOAnagDip e IDBManager aggiunge i parametri
Poi eviterei una MessageBox su una classe per l'accesso ai dati ;) Che ne sai che la tua classe non finisca in un applicativo web o in un servizio windows...
Lascia che l'eccezione venga gestita a più alto livello, se proprio è importante crea una nuova eccezione aggiungendo qualche dettaglio specifico del metodo.

RaouL_BennetH
11-11-2008, 15:12
Basta che fai un metodo privato che data la classe BOAnagDip e IDBManager aggiunge i parametri
Poi eviterei una MessageBox su una classe per l'accesso ai dati ;) Che ne sai che la tua classe non finisca in un applicativo web o in un servizio windows...
Lascia che l'eccezione venga gestita a più alto livello, se proprio è importante crea una nuova eccezione aggiungendo qualche dettaglio specifico del metodo.

Grazie tomminno :)

Per quanto riguarda le eccezioni:

in realtà per il momento non ho ancora focalizzato la mia attenzione su di esse. Più che altro le ho piazzate li per farmi restituire qualcosa a video in caso di errore.

Volevo però farti una domanda:

Cosa intendi per gestire l'eccezione a più alto livello?

Grazie mille :)

RaouL.

RaouL_BennetH
11-11-2008, 16:23
Altra domanda:

Ma come faccio a caricare i vari dati che ottengo per esempio da una:


SELECT * FROM anagip


in una lista anzichè usare datatable o dataset?


Grazie mille :)

RaouL.

tomminno
11-11-2008, 17:20
Altra domanda:

Ma come faccio a caricare i vari dati che ottengo per esempio da una:


SELECT * FROM anagip


in una lista anzichè usare datatable o dataset?


Grazie mille :)

RaouL.

Semplice, te sai quali sono i campi di anagip quindi crei una classe con tutti i campi necessari.

tomminno
11-11-2008, 17:22
Volevo però farti una domanda:

Cosa intendi per gestire l'eccezione a più alto livello?

Grazie mille :)

RaouL.

Semplicemente che la tua classe di accesso ai dati non può gestire correttamente una eccezione e quindi lascia che sia il chiamante (o chiunque nella catena) a gestirla.

0rph3n
11-11-2008, 18:22
Altra domanda:

Ma come faccio a caricare i vari dati che ottengo per esempio da una:


SELECT * FROM anagip


in una lista anzichè usare datatable o dataset?


Grazie mille :)

RaouL.

al posto di usare un DataAdapter e il suo metodo Fill, usi un DataReader che usi per leggere sequenzialmente i dati risultanti dalla query.
ad ogni passaggio istanzi un oggetto del tipo adatto a contenere tali informazioni e lo aggiungi ad una lista :P

esempio

LinkedList<Anagrafica>listaRisultati = new LinkedList<Anagrafica>();

SqlCommand comandoSelezione = connessione.CreateCommand();

SqlDataReader lettoreRisultati = comandoSelezione.ExecuteReader(CommandBehavior.CloseConnection);

while (lettoreRisultati.read())
{
Anagrafica anagraficaCorrente = new Anagrafica();
anagraficaCorrente.ID = lettoreRisultati.getInt32(0);
anagraficaCorrente.Nome = lettoreRisultati.getString(1);
...

listaRisultati.AddLast(anagraficaCorrente);
}


...messo giù così fa abbastanza cacare, però serve solo a rispondere alla tua domanda e "spiegarti" come si usa un DataReader :)

Einstein
12-11-2008, 08:43
...e tra l'altro il metodo Fill dell DataAdapter fa più o meno la stessa cosa: istanzia un DataReader e popola degli oggetti Datarow.

RaouL_BennetH
12-11-2008, 13:32
Ok :)

Seguendo i vostri suggerimenti sono arrivato a fare qualcosa del genere:



private string[] elements = null;

public List<string> GetDatiAnagrafici()
{
//apro la mia connessione al db
try
{
db.Open();
db.ExecuteReader(System.Data.CommandType.Text, selectAnagrafica);
listaDati = new List<string>();
while (db.DataReader.Read())
{
elements = new string[db.DataReader.FieldCount];
db.DataReader.GetValues(elements);
listaComuni.AddRange(elements);
}
return listaDati;
}
catch (Exception e)
{
//blabla
}
finally
{
db.Dispose();
}
}


Utilizzando solo il datareader, boh, forse mi sarò suggestionato, ma mi sembra che sia tutto più veloce.

Ho fatto delle prove popolando diversi tipi di oggetti. La tabella in questione attualmente contiene circa 10.000 records.

Così come ho fatto può andar bene o posso ancora migliorare (non la velocità, non mi interessa) la qualità del codice?


Grazie mille :)

RaouL.

RaouL_BennetH
17-11-2008, 08:58
Altra piccola domanda:

Supposto che io ho un 'business object' ed un data access layer

tra questi chi è il miglior candidato per dialogare con la UI ?

Grazie mille :)

RaouL.

tomminno
17-11-2008, 10:00
Altra piccola domanda:

Supposto che io ho un 'business object' ed un data access layer

tra questi chi è il miglior candidato per dialogare con la UI ?

Grazie mille :)

RaouL.

Business logic!
Il DAL viene usato esclusivamente dal BL.

RaouL_BennetH
17-11-2008, 11:50
Business logic!
Il DAL viene usato esclusivamente dal BL.

perfetto :)

Grazie millissime per il supporto !

RaouL.

Dakko
17-11-2008, 12:12
private string[] elements = null;

public List<string> GetDatiAnagrafici()
{
//apro la mia connessione al db
try
{
db.Open();
db.ExecuteReader(System.Data.CommandType.Text, selectAnagrafica);
listaDati = new List<string>();
while (db.DataReader.Read())
{
elements = new string[db.DataReader.FieldCount];
db.DataReader.GetValues(elements);
listaComuni.AddRange(elements);
}
return listaDati;
}
catch (Exception e)
{
//blabla
}
finally
{
db.Dispose();
}
}



Scusa io non ho capito questo tuo pezzo di codice.
Qual'era la tua intenzione? Cosa dovrebbe fare questo metodo?

Se vuoi fare una cosa pulita invece di costruirti e farti ritornare una lista di stringhe dovresti farti ritornare una lista di oggetti Anagrafica, altrimenti che la hai costruita a fare quella classe? ;)

Edit: cosi' come ti ha suggerito 0rph3n. O forse non ho capito veramente cosa volevi fare :).

RaouL_BennetH
17-11-2008, 13:27
Scusa io non ho capito questo tuo pezzo di codice.
Qual'era la tua intenzione? Cosa dovrebbe fare questo metodo?

Se vuoi fare una cosa pulita invece di costruirti e farti ritornare una lista di stringhe dovresti farti ritornare una lista di oggetti Anagrafica, altrimenti che la hai costruita a fare quella classe? ;)

Edit: cosi' come ti ha suggerito 0rph3n. O forse non ho capito veramente cosa volevi fare :).

Si, hai ragione :)

Quel pezzo di codice mi è servito solo a familiarizzare con le liste.

Nell'implementazione invece uso una lista di 'anagrafica' appunto.

RaouL_BennetH
18-11-2008, 10:29
Ciao a tutti :)

Oggi stavo provando a fare delle transazioni prendendo come modello il link del primo post.

Non riesco ad implementare la transazione.

Qualcuno più scafato potrebbe darmi qualche dritta?



private void Add(BLAnagrafica anagrafica)
{
IDBManager db = new DbManager(DataProvider.Postgresql, miaconnessione);

db.Open();
db.CreateParameters(2);
db.AddParameters(0, "@cognome", anagrafica.Cognome);
db.AddParameters(1, "@nome"; anagrafica.Nome);
db.BeginTransaction();
db.ExecuteNonQuesty(CommandType.Text, "INSERT INTO blabl");
db.CommitTransaction();
}



Non mi va in errore solo che non mi scrive nulla.

Grazie a tutti.

RaouL.

Einstein
18-11-2008, 11:04
Il metodo ExecuteNonQuery() della tua classe IDbManager suppongo istanzi un IDbCommand.
Quel command deve essere a conoscenza della transaction iniziata dal metodo BeginTransaction(), quindi, una volta iniziata la transazione, dovrai passarla al Command (o via costruttore o valorizzando l'apposita proprietà Transaction) prima di chiamare la ExecuteNonQuery().

tomminno
18-11-2008, 14:21
Devi stare attento che se vuoi che la transazione sia comandata dalla Business Logic devi usare delle variabili di classe (per lo meno SqlConnection e SqlTransaction) che sono IDisposable, il che significa che anche la tua classe deve essere IDisposable, con tutto ciò che ne consegue in termini di complessità interna della classe di accesso al db.

RaouL_BennetH
18-11-2008, 14:46
Mamma mia ragazzi !! :ave:

Un altro piccolo tassello grazie a voi è andato al posto giusto.

Non so come ringraziarvi !

RaouL.

RaouL_BennetH
19-11-2008, 09:09
Nuovo giorno .. nuove domande :p

Avendo definito a livello di schema tutto ciò che mi serve sulla mia tabella anagrafica, mi è saltato all'occhio che alla fine, tutte le query di inserimento/aggiornamento sono identiche (eccezion fatta ovviamente per la stringa che definisce il comando).

Ho pensato quindi di non creare ne una lista di 'sqlparameter' ne di creare una query apposita per ogni operazione.

Ho fatto in questo modo e chiedo a voi se può essere considerato sensato oppure devo abbandonare questo ragionamento:



private const string insert = "INSERTO INTO table VALUES (@blabla)";

private const string update = "UPDATE table SET blabla = @blabla WHERE someId = @someId ";

private const string deleteLogical = "UPDATE table SET isActive = 0 WHERE someId = @someId";


private void TestTransaction(BLAnagrafica anag, int actionNumber)
{

//blabla per apertura connessione
//blabla per i sqlparameter
dbManager.CreateParameters(30);
dbManager.AddParameters(0, "@someId", anag.ID);
//etc....

IdbTransaction t = dbManager.BeginTransaction();

switch(actionNumber)
{

case 0:
dbManager.ExecuteNonQuery(CommandType.Text, insert);
t.Commit();
break;

case 1:
dbManager.ExecuteNonQuery(CommandType.Text, update);
t.Commit();
break;

case 2:
dbManager.ExecuteNonQuery(CommandType.Text, deleteLogical);
t.Commit();
break;

default:
break;
}
//blabla
}



Ora, l'esempio è per una sola tabella e quindi potrebbe non essere necessario, ma, mi sono trovato bene avendo altre tabelle che hanno delle relazioni con 'anagrafica' e quindi mi è bastato aggiungere nello switch il relativo comando:



switch (actionNumber)
{

case 0:
dbManager.ExecuteNonQuery(CommandType.Text, insertAnagrafica);
dbManager.ExecuteNonQuery(CommandType.Text, updateAnagraficaRubrica);
//etc..
t.Commit();
//blabla
}


Mi piacerebbe conoscere i vostri suggerimenti e/o critiche.

Grazie mille come sempre :)

RaouL.