Disabilitare e abilitare tutti i trigger di un database SQL Server

by Andrea 17 February 2015 18:05

Nel caso capitasse anche a voi la necessità di disabilitare o abilitare tutti i trigger predenti in un database SQL Server, ho trovato una soluzione davvero comoda a questo link: SQL Server Disabling All Triggers.

-- per disabilitare
sp_MSforeachtable 'ALTER TABLE ? DISABLE TRIGGER all'

-- per abilitare
sp_MSforeachtable 'ALTER TABLE ? ENABLE TRIGGER all'

Tags:

SQL Server

Codice e slide della sessione Windows Azure - Abbattere tempi e costi di sviluppo

by Andrea Dottor 18 June 2013 16:25

Venerdì 7 Giugno 2013 ho tenuto la sessione “Windows Azure - Abbattere tempi e costi di sviluppo”.

In questa sessione vedremo come utilizzare Windows Azure per velocizzare e semplificare la realizzazione di applicazioni ASP.NET. Dallo sviluppo al deploy, passando per lo storage...andremo in dettaglio su varie funzionalità che ci faranno apprezzare ancora più la piattaforma Windows Azure.

 

Qui invece potete scaricare slide e codice della sessione “Riscrivere le query con SQLServer 2012” di Emanuele Zanchettin download

Tags: , , , ,

.NET | ASP .NET | XeDotNet | SQL Server

Avviare un package di SSIS da un'applicazione ASP.NET

by Andrea 29 March 2010 07:22

SSIS Non so come mai, ma utlimamente mi scontro con problematiche non molto documentate. Una di queste è la possibilità di lanciare l'esecuzione di Package di SQL Server Integration Services da un'applicazione ASP.NET.

Cercando in rete, ho trovato solamente due possibili soluzioni, entrambe elencate in questo post. Una soluzione richiede la chiamata ad un job di SQL Server Agent, mentre l'altra soluzione fa uso di un Web Service da pubblicare nella macchina di SQL Server.

La prima soluzione l'ho scartata in quanto non sono riuscito a trovare il metodo per poter passare dei parametri utili a valorizzare le variabili del package (mia ignoranza). Mentre la seconda richiede di installare un'ulteriore applicazione (da dover poi mantenere e ripubblicare), nella macchina di SQL Server, e quindi anche questa scartata.
Può sembrare banale, ma avere un'applicazione in più da mantenere non è sempre semplice, specialmente nel caso l'applicazione sia distribuita in diversi server, e sia presente in casa di diversi clienti.

Guardando le diverse soluzioni, mi è venuta l'idea di provare a adattare la soluzione del Web Service, ma eseguita direttamente da un server remoto. Devo ammettere che ci sono state svariate problematiche, ma alla fine, sono arrivato ad una soluzione perfettamente funzionante.

Ecco come eseguire un package di SSIS da remoto:

Per l'esecuzione del package sarà necessario creare un utente nel database (oppure utilizzarne uno di esistente) ed assegnargli il ruolo db_dtsoperator nel database msdb. Questo ruolo attribuisce all'utente i permessi di:

  • Enumerate all packages.
  • View all packages.
  • Execute all packages.
  • Export all packages.
  • Execute all packages in SQL Server Agent.

Per quanto rigurda la connessione verso il database, nel web.config ho creato una ConnectionString che contiene solamente "Data Source", "User ID" e "Password", questo perchè poi tramite l'uso della classe DbConnectionStringBuilder, verrà poi parsata per recuperarne i singoli valori. Così ho un unico punto dove saranno contenute le credenziali di accesso.

   1: <add 
   2:   name="olapServerAuth"
   3:   connectionString="Data Source=192.168.0.100;User ID=usr;Password=p4$$w0rd;" 
   4:   providerName="System.Data.EntityClient" />

Nell'applicazione sarà necessario referenziare la dll Microsoft.SQLServer.ManagedDTS, e aggiungere alla classe uno using a Microsoft.SqlServer.Dts.Runtime.

Il codice per eseguire il package da remoto sarà il seguente:

   1: // recupero delle informazioni per l'autenticazione al server
   2: DbConnectionStringBuilder cs = new DbConnectionStringBuilder();
   3: cs.ConnectionString = ConfigurationManager.ConnectionStrings["olapServerAuth"].ConnectionString;
   4:  
   5: Application integrationServices = new Application();
   6: // recupero del package che deve essere presente in SQL Server
   7: Package package = integrationServices.LoadFromSqlServer(
   8:                         @"\Data Collector\Test\TestETL",
   9:                         cs["Data Source"] as string,
  10:                         cs["User ID"] as string,
  11:                         cs["Password"] as string,
  12:                         null);
  13:  
  14: // set delle variabili
  15: Variables variables = package.Variables;
  16: variables["VariabileDaSettare"].Value = valoreDaSettare;
  17:  
  18: // set delle connessioni
  19: Connections connections = package.Connections;
  20: connections["AdoNetAnalysisDatabase"].ConnectionString = ConfigurationManager.ConnectionStrings["AdoNetAnalysisDatabase"].ConnectionString;
  21:  
  22: // esecuzione del package
  23: DTSExecResult result = package.Execute(connections, variables, null, null, null);
  24: if (result != DTSExecResult.Success)
  25:     ... // errore nell'esecuzione
  26: else
  27:     ... // avvio corretto del package

Da notare che:

  • DbConnectionStringBuilder: permette di recuperare ogni singolo elemento che compone una ConnectionString. Utile in questo caso per salvare i dati del server di SQL Server, il nome dell'utente di accesso, e la relativa password in un unico container, e poterli poi recuperare singolarmente.
  • Application.LoadFromSqlServer: permette di recuperare un package presente in SQL Server. Se i campi username e password non vengono valorizzati, viene fatto uso della windows authentication.
  • package.Variables: recupero delle variabili utilizzate nel package. Utile nel caso sia necessario modificarne il valore di default prima dell'esecuzione.
  • package.Connections: recupero delle connessioni utilizzate nel package. Da notare che oltre alle stringhe di connessione, compaiono in questa lista anche le connessioni per i Flat File.
    In questi elementi devono essere presenti tutti i valori richiesti, come ad esempio nel caso di una connessione OLEDB dovranno essere presenti: Provider, Application Name e Auto Translate. (per facilità controllate come sono composte nel vostro package).
  • package.Execute: avvia l'esecuzione del package con le nuove variabili e connessioni impostate. 
  • In caso di non successo nell'esecuzione del package, in package.Errors saranno presenti gli errori.

Devo ammettere che ricostruire questo codice non è stato per niente facile, in quanto gli errori che mi si presentavano non erano proprio semplici da decifrare.
La maggiore difficoltà è stata nel capire che le connessioni dovevano riportare tutti i parametri (gli stessi che si possono vedere quando si esegue il package dal SQL Management Studio), ed infine anche il capire quali fossero i permessi minimi da dover dare all'utente per poter eseguire il tutto (per evitare problematiche di sicurezza).
Ma alla fine, tutto ha funzionato alla perfezione, e questo ripaga del tempo speso/investito in questa soluzione.

Tags: ,

SQL Server | ASP .NET | .NET

Reporting Services - creazione di uno snapshot

by Andrea 25 February 2010 08:46

Come scritto nel post precedente, stò dando all'utente finale la possibilità di gestirsi gli snapshot direttamente dall'applicazione, ed ora tocca alla fase di creazione di uno snapshot.

Come ben sapete (e come ho scritto in questo post) gli snapshot vengono creati utilizzando i valori di default dei parametri.
Reporting Services fornisce la possibilità di forzare la creazione di uno snapshot tramite il metodo CreateReportHistorySnapshot, che si comporta esattamente come il pulsante presente nel sito di sharepoint di Reporting, che crea lo snapshot utilizzando i valori dei parametri in quel preciso istante (quindi facendo uso dei valori di default).

Ma se volessimo eseguire uno snapshot che abbia diversi parametri?
E' il caso in cui il report abbia le date o dei filtri calcolati in automatico, magari perchè deve venire eseguito con i dati della settimana precedente, o del mese precedente. Però Il cliente potrebbe avere la necessità di rigenerare il report riferito ad un perioso diverso (magari di 2 settimane prima).
In questo caso si può intervenire andando a modificare da codice i valori di default dei parametri del report, e dopo aver eseguito lo snapshot, ripristinarli ai valori normali.

Ecco qui il codice da qui potete prendere spunto:

   1: using (ReportingService2005SoapClient rs = this.CreateReportingService2005SoapClient())
   2: {
   3:     string batchID = string.Empty;
   4:     ServerInfoHeader infoHeader = rs.CreateBatch(out batchID);
   5:     BatchHeader bh = new BatchHeader()
   6:     {
   7:         BatchID = batchID,
   8:         AnyAttr = infoHeader.AnyAttr
   9:     };
  10:     CatalogItem[] items = null;
  11:     rs.ListChildren(reportFolder, true, out items);
  12:  
  13:     foreach (var item in items)
  14:         if (string.Compare(item.ID, reportId.ToString(), true) == 0)
  15:         {
  16:             // recupero gli attuali parametri e mi tengo una copia degli originali
  17:             ReportParameter[] defaultParameters = null;
  18:             ReportParameter[] parameters = null;
  19:             rs.GetReportParameters(item.Path, null, false, null, null, out defaultParameters);
  20:             rs.GetReportParameters(item.Path, null, false, null, null, out parameters);
  21:  
  22:  
  23:             foreach (ReportParameter parameter in parameters)
  24:             {
  25:                 //modifico i valori dei parametri che voglio cambiare
  26:                 if (string.Compare(parameter.Name, "dateStart", true) == 0)
  27:                     parameter.DefaultValues = new string[] { string.Format("{0:s}", startDate) };
  28:                 else if (string.Compare(parameter.Name, "dateEnd", true) == 0)
  29:                     parameter.DefaultValues = new string[] { string.Format("{0:s}", endDate) };
  30:             }
  31:             // setto i parametri modificati nel report
  32:             rs.SetReportParameters(bh, item.Path, parameters);
  33:             string historyId = string.Empty;
  34:             Warning[] warnings = null;
  35:             // creo lo snapshot
  36:             rs.CreateReportHistorySnapshot(bh, item.Path, out historyId, out warnings);
  37:             // setto i parametri originali
  38:             rs.SetReportParameters(bh, item.Path, defaultParameters);
  39:             // eseguo il tutto sotto un'unica transazione
  40:             rs.ExecuteBatch(bh);
  41:             return;
  42:         }
  43: }

Faccio notare che il tutto viene eseuito sotto un'unica transazione al comando rs.ExecuteBatch(bh), e in caso di errori, il report continuerebbe ad avere i suoi normali valori di default e non i valori da noi modificati.

Technorati Tags: ,

Tags:

SQL Server | Reporting Services | .NET

Reporting Services - cancellare uno snapshot da codice

by Andrea 24 February 2010 03:49

Può capitare di voler dare la possibilità all'utente di cancellare uno snapshot di un determinato report, e dargli la possibilità di farlo direttamente dall'applicazione che abbiamo realizzato.

Oggi mi sono scontrato con questa problematica, e uscirne non è stato proprio immediato a causa della scarsa documentazione a riguardo. Spero quindi che questo post sia utili a qualcuno.

Nella classe ReportingService2005SoapClient (del proxy generato verso il WebService di Reporting Services) esiste un metodo DeleteReportHistorySnapshot che si occupa per l'appunto di cancellare un preciso snapshot (DeleteReportHistorySnapshot), ma il come utilizzarlo è stato un pò oscuro.

Ecco qui il codice finale, che recupera il path del report, conoscendone l'id (scorrendo i report contenuti in una precisa cartella), e successivamente richiama la cancellazione dello snapshot avente l'historyId conosciuto.

   1: using (ReportingService2005SoapClient rs = this.CreateReportingService2005SoapClient())
   2: {                
   3:     string batchID = string.Empty;
   4:     ServerInfoHeader infoHeader = rs.CreateBatch(out batchID);
   5:     BatchHeader bh = new BatchHeader()
   6:     {
   7:         BatchID = batchID,
   8:         AnyAttr = infoHeader.AnyAttr
   9:     };
  10:  
  11:     CatalogItem[] items = null;
  12:     rs.ListChildren(reportFolder, true, out items);
  13:  
  14:     foreach (var item in items)
  15:         if (string.Compare(item.ID, reportId.ToString(), true) == 0)
  16:         {
  17:             rs.DeleteReportHistorySnapshot(bh, item.Path, historyId);
  18:             rs.ExecuteBatch(bh);
  19:         }
  20: }

La difficoltà è stata nel capire cosa fosse il BachHeader, e il di dover chiamare rs.ExecuteBatch,  che si occupa di lanciare i comandi che sono stati inviati utilizzando lo stesso BatchHeader sotto un'unica transazione. Non avendo mai fatto uso (in passato) di metodi a cui viene passato un oggetto BatchHeader, questa soluzione non mi è venuta proprio spontanea.

Ecco un link a riguardo delle operazioni eseguite in batch in reporting services: Batching Methods

Tags:

SQL Server | Reporting Services | .NET

Reporting Services - report snapshots

by andrea 23 July 2009 02:31

Una funzionalità che trovo molto utilie di Reporting Services sono gli Report Snapshots.

Cos'è un report snapshot?

Uno Report Snapshot non è altro che una copia del report, eseguito in un preciso istante. Questa copia conterrà tutte le informazioni necessarie per permettere di visualizzare il report in un secondo momento, e avere lo stato al momento della sua creazione.

Quando viene chiesto di salavare uno snapshots, Reporting Services esegue il report in questione e immagazzina tutte le informazioni che vanno a popolare i dataset utilizzati nel report stesso (e anche il layout del report). In questo modo, quando viene richiesta la visualizzazione di un preciso Snapshot, si hanno a disposizione i dati già elaborati, che erano presenti in quel preciso istante (data + ora).
Ecco cosa viene salvato nel server di Reporting Services:

  • The result set (that is, the data in the report, retrieved through the credentials specified in the Data Sources properties page of the report).
  • The underlying report definition, as it exists at the time the snapshot was created. If the report definition was subsequently modified after the snapshot was generated, those changes are not reflected in the snapshot.
  • Parameter values that are used to obtain or filter the result set.
  • Embedded resources, such as images. External resources that are linked to a report are not stored with the report snapshot.

Un enorme vantaggio, che porta all'uso dei Report Snapshots, è il fatto di poter essere schedulati, ed esistono molte impostazioni possibili a riguardo. (esecuzione a intervalli prestabiliti, in precisi giorni, una sola volta, ...)

I Report Snapshots hanno però anche delle limitazioni, una di queste, è dovuta al fatto che vengono salvanti anche i valori dei parametri, e questo comporta che se vogliamo Snapshot con parametri differenti, si dovranno creare differenti Report (o Linked Reports), ma questo è anche capibile.
In alcune condizioni però, è possibile utilizzare un parametro (visibile) all'interno del report per filtrare i dati. Infatti, il filtro dei dati all'interno del report è una prassi consentita, in quanto viene applicato ai dati che popolano i DataSet (e quindi immagazzinati nello snapshot)

Quando utilizzare i report snapshots?

Possono essere utilizzati prevalentemente per due motivazioni:

  • Si vuole avere uno storico di un determinato report.
    Schedulando la creazione di snapshot a determinati intervalli, permettono di avere esattamente la situazione (il risultato del report) in quel dato momento, e quindi poter eseguire a posteriore una visualizzazione di tali dati.
  • Esecuzione di report che richiedono molto tempo di elaborazione.
    E' possibile schedulare l'esecuzione di snapshot per ovviare al problema dell'attesa per l'elaborazione di report che richiedono un lungo tempo di caricamento. In questo modo, l'utente può visualizzare l'ultimo snapshot eseguito, che verrà caricato velocemente in quanto i dataset sono già stati popolati durante la creazione dello snapshot, risparmiando così l'attesa all'utente.

Come visualizzare uno snapshot nel controllo ReportViewer

Per visualizzare uno snapshot di un preciso report nel controllo ReportViewer è sufficiente impostare la proprietà HistoryId del controllo, con l'ID dello snapshot che si vuole visualizzare.

reportViewer.ServerReport.HistoryId = historyID;

Utilizzando il web service esposto da Reporting Services (Consumare il web service di Reporting Services) è possibile recuperare la lista di Snapshots di un determinato report, e utilizzare i dati ricevuti per recuperare l'identificativo dell'ultimo Snapshot eseguito.
Ecco come poter recuperare la lista di tutti gli snapshot di un determinato report:

   1: public ReportHistorySnapshot[] GetReportHistory(string reportFullPath)
   2: {
   3:   using (ReportingService2005SoapClient rs = ReportingService2005SoapClient())
   4:   {
   5:       rs.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
   6:       rs.ClientCredentials.Windows.ClientCredential.UserName = "username";
   7:       rs.ClientCredentials.Windows.ClientCredential.Password = "password";      
   8:  
   9:       ReportHistorySnapshot[] snapshots = null;
  10:       rs.ListReportHistory(reportFullPath, out snapshots);
  11:  
  12:       return snapshots;
  13:   }
  14: }

Link:

Tags: ,

SQL Server | .NET | Reporting Services

Consumare il web service di Reporting Services

by andrea 16 July 2009 08:05

Ecco come utilizzare il web service di Reporting Services (utilizzando basicHttpBinding)
(sia per Reporting Services 2005 che per Reporting Services 2008)

Per poter utilizzare il (uno dei) web service esposto da Reporting Serives, si dovrà creare una Service Reference facendola puntare all'url
http://127.0.0.1/reportserver/ReportService2005.asmx?wsdl
dove 127.0.0.1 sarà l'IP della macchina dove è installato Reporting Services.

Aggiunta la referenza, verrà automaticamente generata la configurazione all'interno dell'app.config, e nell'elemento basicHttpBinding saranno da modificare:

  • in binding --> security: modificare l'attributo mode in TransportCredentialOnly
  • in binding --> security --> transport: impostare clientCredentialType e proxyCredentialType a Ntlm

La configurazione finale sarà quindi la seguente:

   1: <system.serviceModel>
   2:     <bindings>
   3:         <basicHttpBinding>
   4:             <binding name="ReportingService2005Soap" closeTimeout="00:01:00"
   5:                 openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
   6:                 allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
   7:                 maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
   8:                 messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
   9:                 useDefaultWebProxy="true">
  10:                 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  11:                     maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  12:                 <security mode="TransportCredentialOnly">
  13:                     <transport clientCredentialType="Ntlm" proxyCredentialType="Ntlm"
  14:                         realm="" />
  15:                     <message clientCredentialType="UserName" algorithmSuite="Default" />
  16:                 </security>
  17:             </binding>
  18:         </basicHttpBinding>
  19:         <customBinding>
  20:             <binding name="ReportingService2005Soap12">
  21:                 <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
  22:                     messageVersion="Soap12" writeEncoding="utf-8">
  23:                     <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  24:                         maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  25:                 </textMessageEncoding>
  26:                 <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
  27:                     maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Ntlm"
  28:                     bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
  29:                     keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Ntlm"
  30:                     realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
  31:                     useDefaultWebProxy="true" />
  32:             </binding>
  33:         </customBinding>
  34:     </bindings>
  35:     <client>
  36:         <endpoint address="http://127.0.0.1:80/ReportServer/ReportService2005.asmx"
  37:             binding="basicHttpBinding" bindingConfiguration="ReportingService2005Soap"
  38:             contract="ReportingServices.ReportingService2005Soap" name="ReportingService2005Soap" />
  39:     </client>
  40: </system.serviceModel>

Ora, per poter invocare i metodi del web service è necessario impersonare un utente della macchina di Reporting Services (che abbia i diritti correttamente impostati), andando a settare i valori nelle rispettive proprietà della classe ClientCredentials.

Impersonato l'utente, sarà poi possibile invocare i metodi esposti dal servizio.

   1: using (ReportingService2005SoapClient rs = new ReportingService2005SoapClient())
   2: {
   3:     rs.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
   4:     rs.ClientCredentials.Windows.ClientCredential.UserName = "username";
   5:     rs.ClientCredentials.Windows.ClientCredential.Password = "password";
   6:     rs.ClientCredentials.Windows.ClientCredential.Domain = "domain";    
   7:  
   8:     CatalogItem[] items = null;
   9:     rs.ListChildren("/", true, out items);
  10:     // [...]
  11: }

Alcune ulteriori informazioni le potete trovare al seguente link:
Reporting Services Web Service

Per un progetto a cui stò lavorando, ho dovuto fare uno studio per alcune funzionalità che dovevano pesantemente interagire con il web service di Reporting Services.
Ho notato che le informazioni in rete sono un pò sparse e frazionate, e quindi mi è sembrato utile scrivere due righe per aiutare chi fosse ai primi passi (su questa problematica).

Tags:

ASP .NET | .NET | SQL Server | Reporting Services

Community Meeting - SQL Server 2008: Le novità

by Andrea 20 November 2008 02:26

Venerdì 21 Novembre si terrà il XeDotNet community meeting dal titolo SQL Server 2008: Le novità e tenuto da Simone Corsini.

Ecco l'abstract:

Una rapida carrellata su le principali novità di SQL Server 2008. Toccando punti come sicurezza, gestione, business inteligence, reportistica. E ovviamente toccando anche punti un po' più interessanti anche per gli sviluppatori come i nuovi tipi di dato e gestione dei tipi destrutturati.

Per iscriversi il link è http://www.xedotnet.org/nextmeeting.aspx.

E come in tutti i community meeting che si rispettino, alla fine del meeting ci sarà il solito ritrovo allo scarpon a Mestre per fare della sana e buona attività di community davanti ad un bel panino.

Tags:

SQL Server | XeDotNet

SQL Server - Ripristinare un utente dopo un restore

by Andrea 13 September 2007 22:09

Se state facendo un restore di un database, e magari usando un backup fatto su un'altro server, può capitare che abbiate problemi di autenticazione quando provate ad accedervi dalla vostra applicazione.
Questo può accadere perchè l'utente e i suoi permessi non sono allineati con quelli del nuovo SQL server.

Per fixare l'utente e i ruoli è sufficiente eseguire la seguente store procedure:

EXEC sp_change_users_login 'Auto_Fix', 'user', NULL, 'pwd';

Maggiori info: sp_change_users_login (Transact-SQL)

Tags:

SQL Server

Conoscere la versione di SQL Server

by andrea 02 August 2007 23:08

Questa me la devo proprio segnare perchè so già che mi tornerà presto utile.smile_wink
Per conoscere la versione di SQL Server installata è sufficiente eseguire questa Query:

SELECT  @@version, 
        SERVERPROPERTY('productversion'), 
        SERVERPROPERTY ('productlevel'), 
        SERVERPROPERTY ('edition')

e otterete dei dati simili ai seguenti:

Version: Microsoft SQL Server 2005 - 9.00.2050.00 (Intel X86)   Feb 13 2007 23:02:48   Copyright (c) 1988-2005 Microsoft Corporation  Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
ProductVersion: 9.00.2050.00
ProductLevel: SP1
Edition: Standard Edition

Fonte: How to identify your SQL Server version and edition

Technorati tags:

Tags:

Reporting Services | SQL Server