|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
[C#] DAL/CRUD
....
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: Codice:
private void buttonSalva_Click(object sender, EventArgs e)
{
try
{
DataBase d = new DataBase();
d.Open();
d.Insert(text1.text, et....);
}
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? ![]() Grazie mille. RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
uppettino....
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#4 | ||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
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. Quote:
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 Ultima modifica di tomminno : 09-11-2008 alle 11:40. |
||
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
grazie Tomminno.
Avresti quindi qualche suggerimento da darmi ? che so... esempi, link, schemi... Grazie mille. RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Buondì
Ho lasciato perdere il dataset e sto procedendo in quest'altra direzione: In una libreria separata, sto ricreando lo schema del database: Codice:
//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
Codice:
//Data Access Layer per Anagrafica
public class DALAnagrafica
{
//da implementare
}
Grazie mille RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jan 2000
Città: Provincia di Parma
Messaggi: 724
|
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: Codice:
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
}
}
Codice:
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
}
}
Voglio solo metterti davanti un po' di soluzioni, e nessuna di queste è necessariamente meglio dell'altra: dipende sempre dal tuo contesto applicativo.
__________________
My Pc: Case Enermax Chakra - PSU Corsair HX520 - Gigabyte P35-DS3R - Core2 Duo E6550 - 6 Gb RAM Geil PC800 - 2x WD Caviar SE 320Gb (Raid1) - Xfx GeForce 8600Gt - Master Pioneer DVR111D - Samsung SM T220 - S.O. Windows 7 Ultimate x64 SP1 My blog: http://blogs.ugidotnet.org/alby Ultima modifica di Einstein : 10-11-2008 alle 12:35. |
|
|
|
|
|
#8 | |||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Ripeto avevano un senso quando ancora non c'era il supporto ai generics (ovvero nella versione beta del .NET qual era la 1.1) Quote:
Quote:
Ad oggi un DAL scritto a mano che utilizza delle classi contenitore (solo get e set) è la soluzione da adottare nei casi semplici. |
|||
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Jan 2000
Città: Provincia di Parma
Messaggi: 724
|
e domani potrebbe non esserci più...
http://blogs.msdn.com/adonet/archive...s-roadmap.aspx Che attualmente non mi sembra 'sta gran cosa. Infatti ha una curva di apprendimento piuttosto ripida Quote:
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.
__________________
My Pc: Case Enermax Chakra - PSU Corsair HX520 - Gigabyte P35-DS3R - Core2 Duo E6550 - 6 Gb RAM Geil PC800 - 2x WD Caviar SE 320Gb (Raid1) - Xfx GeForce 8600Gt - Master Pioneer DVR111D - Samsung SM T220 - S.O. Windows 7 Ultimate x64 SP1 My blog: http://blogs.ugidotnet.org/alby |
|
|
|
|
|
|
#10 | |||||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Quote:
Quote:
Quote:
Quote:
|
|||||
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
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.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Iscritto! Mi interessa molto questo thread, tienici aggiornati se puoi
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Feb 2003
Città: Stockholm (SE)
Messaggi: 1343
|
Quote:
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. Codice:
public class Person {}
public class PersonCollection : List<Person> {}
|
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
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 Codice:
//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; }
}
}
}
Codice:
//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();
}
}
}
}
Codice:
//dal form poi, mi basta semplicemente chiamare Add() e per la prima volta anche se cambio layout grafico non devo toccare nulla. Inutile dirvi che accetto qualsiasi tipo di suggerimento, critica o qualsiasi altra cosa che possa farmi crescere. Grazie mille RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Poi eviterei una MessageBox su una classe per l'accesso ai dati Lascia che l'eccezione venga gestita a più alto livello, se proprio è importante crea una nuova eccezione aggiungendo qualche dettaglio specifico del metodo. |
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Quote:
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.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Altra domanda:
Ma come faccio a caricare i vari dati che ottengo per esempio da una: Codice:
SELECT * FROM anagip Grazie mille RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek
|
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Semplice, te sai quali sono i campi di anagip quindi crei una classe con tutti i campi necessari.
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
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.
|
|
|
|
|
|
#20 | |
|
Senior Member
Iscritto dal: Apr 2005
Città: Resana - TV
Messaggi: 960
|
Quote:
ad ogni passaggio istanzi un oggetto del tipo adatto a contenere tali informazioni e lo aggiungi ad una lista :P esempio Codice:
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);
}
|
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:52.





















