Articoli con tag C#

Esportare schema del db da NHibernate – NHibernate SchemaExport

Nota: Articoli etichettati come Snippet non contengono codice completo ma solo parti di esso, recuperate da appunti. Per cui, potrebbe essere necessario modificarne alcuni nomi o indici. Per ogni chiarimento, lasciate un commento all’articolo.

Dopo aver configurato correttamente NHibernate con tutti i file di mapping ed aver definito correttamente i parametri di connessione, è possibile lasciare al framework l’onere di costruire il database.

Un vincolo importante (nel caso decidiate di eseguire l’export) è che il database (vuoto) esista sul DBMS e che l’utente sia autorizzato alla creazione di tabelle e vincoli.

A mio parere questa funzionalità andrebbe utilizzata solo come metodo di verifica della correttezza del mapping (ad esempio facendo creare un db parallelo per i confronti) e non per una generazione da “produzione”, almeno se non seguita da un profondo controllo manuale…

private static string mappingFilePath = “Mapping\\hibernate.cfg.xml”;

NHibernate.Tool.hbm2ddl.SchemaExport se = new NHibernate.Tool.hbm2ddl.SchemaExport(new NHibernate.Cfg.Configuration().Configure(mappingFilePath));

se.Create(true, false);

Ho inserito il percorso completo dei Namespace, ovviamente è possibile utilizzare normalmente la direttiva “using”.
I due parametri del metodo .Create indicano se si desidera generare lo scritpt in console e se si desidera esportare il mapping sul db (creare fisicamente le tabelle & co…)

Per info più approfondite, il link di riferimento (su Hibernate) è:
http://docs.jboss.org/hibernate/orm/3.3/api/org/hibernate/tool/hbm2ddl/SchemaExport.html

Annunci

, ,

Lascia un commento

Nascondere una proprietà in datagridview – hide property in datagridview – C#

Nota: Articoli etichettati come Snippet non contengono codice completo ma solo parti di esso, recuperate da appunti. Per cui, potrebbe essere necessario modificarne alcuni nomi o indici. Per ogni chiarimento, lasciate un commento all’articolo.

Quando si effettua un binding diretto tra una IList (risultato da una query su database) di oggetti ed una Datagridview, automaticamente tutte le proprietà pubbliche della classe di cui gli oggetti fanno parte vengono visualizzate come colonne della dgv stessa.

In alcuni casi può essere necessario nascondere alcune colonne. I metodi sono due anche se personalmente preferisco il secondo.

//dgvElenco è il nome della DataGridView e “id” è la proprietà da nascondere
dgvElenco.Columns[“id”].Visible = false;  

Questo primo metodo porta l’impostazione di una colonna del controllo a visible = false e quando la uso, inserisco questo codice subito dopo la procedura di binding. In tal modo, però, la definizione di colonna “nascosta” viene portata nel codice, nella logica dell’applicazione, piuttosto che nella definizione della classe. Questa è invece la seconda strada percorribile.

[Browsable(false)]
public bool nonPersistente { get; set; }

Utilizzando l’attributo “Browsable” del namespace System.ComponentModel è possibile definire all’interno della classe stessa il “nascondimento” (!!!) della specifica proprietà

 

,

Lascia un commento

Passare il contenuto di un file in standard input -stdin- ad un’applicazione

Qualche tempo fa, quando il DOS e la riga di comando la facevano ancora da padrone, era frequente l’uso del reindirizzamento dello standard input/output/error (stdin, stdout, stderr) per passare il contenuto di un file ad un applicativo e farlo elaborare.

Mi capita ancora di utilizzare questa tecnica con i tool da riga di comando del database MySql.

Per esempio, per importare un dump o uno script sql in un db, è sufficiente digitare (da cmd.exe) il seguente testo

mysql -h 192.168.1.1 -u user -ppwd dbname < C:\updateDb.sql

Questo fa si che lo script contenuto nel file updateDb.sql venga interpretato dal mysql come se immesso a mano da tastiera.

Qualche giorno fa, invece, ho avuto la necessità di automatizzare questo processo all’interno di un’applicazione C#.

Di seguito riporto il codice utilizzato ed al suo interno i commenti necessari

            //Aggiornamento db
            try
            {               
                FileInfo file = new FileInfo(Config.sqlUpdateScript); //sqlUpdateScript è il percorso di updateDb.sql
                if (file.Exists)
                {

                    //Config.applicazioneDbUpdate rappresenta il file dell’applicazione da eseguire: mysql.exe
                    ProcessStartInfo appDump = new ProcessStartInfo(Config.applicazioneDbUpdate);
                    appDump.WindowStyle = ProcessWindowStyle.Hidden;
                    appDump.UseShellExecute = false;
                    appDump.RedirectStandardError = true;
                    appDump.RedirectStandardOutput = true;
                    appDump.RedirectStandardInput = true;
                    //Le credenziali vengono passate come stringhe e concatenate da string.Format
                    appDump.Arguments = string.Format(“-h {0} -u {1} -p{2} {3}”, server, userid, password, database);
                    Process p = Process.Start(appDump);

                    //Apro lo StreamReader verso il file di script sql
                    using (var streamReader = new StreamReader(Config.sqlUpdateScript))
                    {
                       //QUESTA E’ LA PARTE PRINCIPALE: passo il file allo StandardInput del processo “p”
                        p.StandardInput.Write(streamReader.ReadToEnd());
                        p.StandardInput.Flush();
                        p.StandardInput.Close();
                    }

                   //Verifico eventuali output del programma o messaggi di errore
                    string output = p.StandardOutput.ReadToEnd();   //Lettura prima di WaitForExit, altrimenti si blocca
                    string outerr = p.StandardError.ReadToEnd();
                    p.WaitForExit(60000); //60 secondi

                    if (p.ExitCode != 0)
                    {
                        //LogMe.log(…) è un metodo di una -mia- classe di log
                        LogMe.log(LogLevel.Error, outerr);
                        LogMe.log(LogLevel.Error, appDump.Arguments);
                        MessageBox.Show(“Impossibile completare il backup\n” + outerr, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return false;
                    }
                }
                else
                {
                    LogMe.log(LogLevel.Error, “Script di aggiornamento non trovato!”);
                    MessageBox.Show(“Script di aggiornamento non trovato!\nAggiornamento non riuscito.”, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            catch (Exception exe)
            {
                LogMe.log(LogLevel.Error, exe);
                MessageBox.Show(“Errore generico\n” + exe.Message, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

, , ,

Lascia un commento

NHibernate, utilizzo di liste comma separated per clausola WHERE IN – setParameter

Nota: Articoli etichettati come Snippet non contengono codice completo ma solo parti di esso, recuperate da appunti. Per cui, potrebbe essere necessario modificarne alcuni nomi o indici. Per ogni chiarimento, lasciate un commento all’articolo.

Se vi è la necessità di utilizzare, all’interno di una query HQL (Hibernate Query Language), la clausola “WHERE qualcosa IN”, Nhibernate fornisce la possibilità di utilizzare (anche per questo caso) le query parametriche, ovvero di evitare la creazione di query mediante concatenazione del testo.

Esempio:/* Lista di id: 3, 5, 9 */

— Concatenazione — Metodo poco elegante e poco “object oriented”

string listaId = “3, 5, 9”;  // Stringa creata mediante funzioni di concatenazione, es: string.join(…)
string myQuery = “UPDATE Assegnazione a SET a.qtaRendere = null WHERE a.id IN (” + listaId + “)”;

— Query parametrica — Bel metodo!

ArrayList listaIdAssegnazioni = new ArrayList();
listaIdAssegnazioni.Add((int)mle.idAssegnazione);  //Ripetuta per ogni id!

string myQuery = “UPDATE Assegnazione a SET a.qtaRendere = null WHERE a.id IN (:elencoId)”;
var qry = [ISession].CreateQuery(myQuery);  //con [ISession] si intende l’oggetto di tipo ISession già creato precedentemente
qry.SetParameterList(“elencoId”, listaIdAssegnazioni.ToArray(typeof(int)));
qry.ExecuteUpdate();

 

, ,

Lascia un commento

Aggiornamento textbox in binding, quando si modifica il valore dell’oggetto – update textbox binding

Nota: Articoli etichettati come Snippet non contengono codice completo ma solo parti di esso, recuperate da appunti. Per cui, potrebbe essere necessario modificarne alcuni nomi o indici. Per ogni chiarimento, lasciate un commento all’articolo.

Qualora sia necessario forzare il valore di un oggetto messo in Binding con una textbox e si voglia riscontrare immediatamente tale cambiamento nel testo del controllo, eseguire il comando “ReadValue()”

i_assegnazione.qtaRendere = qtaRendereOriginale;
txtQtaRendere.DataBindings[0].ReadValue();

 

,

Lascia un commento

Backup Mysql con mysqldump.exe – Parametri dell’applicazione

Nota: Articoli etichettati come Snippet non contengono codice completo ma solo parti di esso, recuperate da appunti. Per cui, potrebbe essere necessario modificarne alcuni nomi o indici. Per ogni chiarimento, lasciate un commento all’articolo.

Per effettuare il dump di un database MySql all’interno di una applicazione C#, mediante l’applicazione ufficiale mysqldump.exe.

Sono stati commentati i pezzi relativi al redirect dello standard output perchè nella prima versione, l’output del programma veniva poi salvato su file. Il problema è che in tal modo eventuali caratteri UTF (es: °) non venivano correttamente esportati perchè il redirect non gestisce la codifica UTF-8, mentre tutto viene esportato correttamente mediante “–result-file”.

string dumpFileName = “backupDb_” + String.Format(“{0:yyyy_MM_dd_HH_mm}”, DateTime.Now) + “.sql”;

string applicazioneDbDump = @”c:\………..\mysqldump.exe”;

try
{
ProcessStartInfo appDump = new ProcessStartInfo(applicazioneDbDump);
appDump.WindowStyle = ProcessWindowStyle.Hidden;
appDump.UseShellExecute = false;
appDump.RedirectStandardError = true;
//appDump.RedirectStandardOutput = true;
//–skip-lock-tables >> Senza questo parametro, in vecchie versioni di MySql server, genera errore [mysqldump: Got error: 1044: Access denied for user ‘utente’@’%’ to database ‘nomedb’ when using LOCK TABLES]
appDump.Arguments = string.Format(“-h {0} –database {1} -u {2} -p{3} –skip-add-drop-table –skip-disable-keys –skip-set-charset –skip-lock-tables –result-file=\”{4}\””, server, database, userid, password, Config.percorsoApplicazione + “\\BackupDb\\” + dumpFileName);

Process p = Process.Start(appDump);
//string output = p.StandardOutput.ReadToEnd();   //Lettura deve essere effettuata prima di WaitForExit, altrimenti si blocca
string outerr = p.StandardError.ReadToEnd();
p.WaitForExit(60000); //60 secondi

if (p.ExitCode != 0)
{
LogMe.log(LogLevel.Error, outerr);
LogMe.log(LogLevel.Error, appDump.Arguments);
Func.disattivaProgressBar();
MessageBox.Show(“Impossibile completare il backup\n” + outerr, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
catch (Exception e)
{
LogMe.log(LogLevel.Error, e);
Func.disattivaProgressBar();
MessageBox.Show(“Impossibile avviare il backup\n” + e.Message, Config.titolo, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

, , ,

1 Commento

Utilizzare un Enum come DataSource per una ComboBox – Enums as DataSource

Eccomi ancora una volta a riportare sul blog la soluzione di un problemino di programmazione che mi ha appena fatto perdere un paio d’ore…

Preciso subito quali sono le fonti; il codice è stato preso e riadattato da due siti web, i quali trattavano l’argomento ma con delle piccole differenze rispetto a quanto servisse a me, e da un riferimento a msdn Microsoft.

http://stackoverflow.com/questions/1177915/binding-a-datasource-with-some-enum-values
http://developcode.blogspot.com/2006/12/dropdownlists-with-enums-as-datasource.html
http://msdn.microsoft.com/it-it/library/5tbh8a42%28v=VS.90%29.aspx

Il problema è il seguente: utilizzare un Enum in C# per popolare una ComboBox, visualizzando gli alias testuali ma utilizzando i valori numerici sottostanti per eseguire l’associazione manuale con un oggetto, da persistere mediante NHibernate.

L’oggetto in gestione è “Utente”, che ha diversi permessi per l’accesso all’applicazione. Di seguito la definizione dell’Enum:

public enum LivelloAccesso { Magazzino = 1, Ufficio = 2, Amministratore = 3};

Notare che ho esplicitato il valore delle costanti in Enum, al fine di essere sicuro di quali valori NH avrebbe poi salvato sul database.

Per completezza, nel mapping di NH ho indicato la proprietà come Int32

<property name=”livelloAccesso” column=”livelloAccesso” type=”Int32″ />

mentre nel codice

public virtual LivelloAccesso livelloAccesso { get; set; }

in modo che NH fosse in grado di effettuare automaticamente il mapping tra valori enum e gli Int32 associati.

Tornando all’argomento principale, questo è il codice utilizzato per mappare l’enum LivelloAccesso su una ComboBox in grafica:

List<KeyValuePair<int, string>> listaLivelliAccesso = new List<KeyValuePair<int, string>>();
foreach (Enum enumValue in Enum.GetValues(typeof(LivelloAccesso)))
{
listaLivelliAccesso.Add(new KeyValuePair<int, string>(Convert.ToInt16(enumValue),
enumValue.ToString()));
}
cmbLivelloAccesso.DataSource = listaLivelliAccesso;
cmbLivelloAccesso.DisplayMember = “Value”;
cmbLivelloAccesso.ValueMember = “Key”;

Questo il risultato grafico:

Da notare che non ho usato il termine Binding perchè l’associazione tra la combo e la proprietà dell’oggetto viene effettuata “a mano” mediante il seguente codice:

cmbLivelloAccesso.SelectedValue = Convert.ToInt32(i_utente.livelloAccesso);

Ovviamente conversione inversa dovrà essere fatta in fase di salvataggio dell’oggetto. Al momento non ho ancora completato il codice, per cui non riporto tale conversione, rimandando la sua scrittura su un eventuale commento successivo.

Una evoluzione potrebbe essere quella di eseguire il vero e proprio Binding tra la combo e l’oggetto… Chi mi aiuta? 😉

,

Lascia un commento

Inserire in una colonna di datagridview una immagine

Nota: Articoli etichettati come Snippet non contengono codice completo ma solo parti di esso, recuperate da appunti. Per cui, potrebbe essere necessario modificarne alcuni nomi o indici. Per ogni chiarimento, lasciate un commento all’articolo.

Questo stralcio di codice consente di inserire, in una datagridview (C# – Windows Forms), una colonna contenente immagini.

Nell’esempio sono stati utilizzati dei pallini colorati, per indicare lo stato dei singoli record visualizzati.

Viene inoltre fornito il codice per modificare, a runtime, l’immagine della specifica riga nella colonna di immagini.

DataGridViewImageColumn colonna = new DataGridViewImageColumn();
colonna.ImageLayout = DataGridViewImageCellLayout.Normal;
colonna.Image = new System.Drawing.Bitmap(Properties.Resources.pallino_rosso);
dgvConvocazioni.Columns.Insert(1, colonna);
dgvConvocazioni.Columns[1].HeaderText = “”;
dgvConvocazioni.Columns[1].Width = 20;

Modifica a RunTime

dgvConvocazioni.Rows[1].Cells[5].Value = New System.Drawing.Bitmap(Properties.Resources.pallino_verde)

Se il DataSource della dgv è una lista (Ilist) di oggetti, è sufficiente inserire tra le proprietà della classe una Bitmap.
Segue il codice di definizione della classe, la cui lista rappresenta il DataSource.

    public class DatagridListElementConvocazioni
{
public int id { get; set; }
[DisplayName(” “)]       // Richiede: using System.ComponentModel;
public System.Drawing.Bitmap stato { get; set; }
[DisplayName(“Data Invio”)]
public string dataInvio { get; set; }

public DatagridListElementConvocazioni(……)
{
….
this.stato = new System.Drawing.Bitmap(Properties.Resources.pallino_bianco);

}
}

,

Lascia un commento

Stampa di un Report (rdlc) in Visual Studio senza anteprima e con numero di copie selezionabile

Questa sera, sviluppando un software gestionale in C# (Visual Studio 2008 – .Net Framework 3.5) mi sono trovato davanti ad un problema. Ho la necessità di mandare in stampa un Report (estensione rdlc) realizzato con il Report Designer di Visual Studio, senza passare per l’anteprima e con un numero di copie variabile.

Cercando (“c# print report without preview“) sui numerosi forum che trattano di programmazione, ho trovato molti post che fanno riferimento ad un articolo Microsoft, presente in http://msdn.microsoft.com/en-us/library/ms252091.aspx

Mi sono letto l’articolo, ho cercato di capirne il funzionamento ed ho deciso di scrivere una classe che mi permettesse di stampare senza troppa fatica un Report esistente. L’unico metodo pubblico della classe permette anche di selezionare il numero di stampe da effettuare.

Le modifiche al codice, rispetto a quello dell’articolo, sono minime e riguardano appunto quest’ultima funzione e la capacità della classe di ricavare le dimensioni ed i margini del Report direttamente dall’oggetto passato.

PrintReport.cs

Nella classe chiamante, impostare il Report locale personalizzando il seguente codice:

            LocalReport lr = new LocalReport();
lr.ReportPath = reportPath;
lr.EnableExternalImages = true;
lr.DataSources.Add(source);
lr.SetParameters(parameters);
lr.Refresh();

con “source” una sorgente dati valida e “parameters” un array di parametri.

Appena avrò un attimo di tempo, scriverò un articolo completo sulla preparazione e stampa dei Report in Visual Studio, almeno per quanto appreso nella mia esperienza! 😉

AGGIORNAMENTO della Classe – versione 1.0.1 – 12 ottobre 2011

Dalle statistiche ho notato che il file allegato a questo articolo è stato scaricato numerose volte. Vi chiedo cortesemente, in caso utilizziate il file, di lasciare un commento sulla classe. Impressioni, bug, proposte di miglioramenti (anche effettuati). Grazie!!!

, ,

2 commenti