<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>SQL</title>
        <link>http://blogs.ugidotnet.org/PietroLibroBlog/category/SQL.aspx</link>
        <description>SQL</description>
        <language>it-IT</language>
        <copyright>Pietro Libro</copyright>
        <managingEditor>pietro.libro@libero.it</managingEditor>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>Documentazione EF 7 (Beta 5)</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2015/07/22/documentazione-ef-7-beta-5.aspx</link>
            <description>Documentazione "Work in Progress" della prossima release di Entity Framework : http://ef.readthedocs.org/en/latest/&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/102030.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2015/07/22/documentazione-ef-7-beta-5.aspx</guid>
            <pubDate>Wed, 22 Jul 2015 09:07:28 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2015/07/22/documentazione-ef-7-beta-5.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/102030.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/102030.aspx</trackback:ping>
        </item>
        <item>
            <title>EF 6.1 : What&amp;rsquo;s new (3)</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/03/27/ef-6.1-whatrsquos-new-3.aspx</link>
            <description>Supporto a “.ToString()” e “String.Concat()”, un esempio:  var queryConcat = from c in db.Vehicles
            where string.Concat(c.EngineSize, c.HP).Equals("1600110")
            select c;

var queryToString = from c in db.Vehicles
            where  c.HP.ToString().Equals("110")
            select c;


 

Abbiamo due Query LINQ che filtrano i dati in base a condizioni su stringhe, la prima “tira fuori” tutti i veicoli dove la concatenazione dei valori delle proprietà “EngineSize” e “HP” è uguale a “1600110”, mentre la seconda esegue un filtro su di un valore intero convertio in stringa. Se proviamo ad eseguire il codice in un ambiente con EF 6.0 otteniamo un’eccezione a runtime in tutti e due i casi:



Con EF 6.1 le query sono eseguite correttamente:



Cosa succede dietro le quinte:

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [DomusDotNet].[Vehicles] AS [Extent1]
        WHERE N'1600110' = (CASE WHEN ([Extent1].[EngineSize] IS NULL) THEN N'' ELSE [Extent1].[EngineSize] END +  CAST( [Extent1].[HP] AS nvarchar(max)))
    )  AS [GroupBy1]

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [DomusDotNet].[Vehicles] AS [Extent1]
        WHERE N'110' =  CAST( [Extent1].[HP] AS nvarchar(max))
    )  AS [GroupBy1]




Da analizzare il funzionamento di “String.Concat(…)” con SQL Server 2012 per verificare la conversione in SQL con la funzione “nativa SQL” “Concat”.&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101829.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/03/27/ef-6.1-whatrsquos-new-3.aspx</guid>
            <pubDate>Thu, 27 Mar 2014 10:04:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2014/03/27/ef-6.1-whatrsquos-new-3.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101829.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101829.aspx</trackback:ping>
        </item>
        <item>
            <title>EF 6 : Logging &amp;amp; Interception</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/09/04/ef-6-logging-amp-interception.aspx</link>
            <description>   Una delle nuove feature introdotte nella versione 6 di Entity Framework (attualmente in RC) è il supporto al logging dell’SQL generato dal runtime di EF6. A tal fine è sufficiente passare un opportuno delegate alla proporietà Log esposta da DbContext.Database. Per gli esempi riprendiamo lo scenario del post precedente.   Supponiamo di avere il seguente codice:   using (CarContext db = new CarContext())
{
 
    System.Console.WriteLine("Cars in database : {0}", db.Cars.Count());

    ////Add a new car.
    Car car = new Car()
    {
        Brand = "Alfa Romeo",
        Model = "Giulietta"
    };

    db.Cars.Add(car);
    db.SaveChanges();

    System.Console.WriteLine("Cars in database : {0}", db.Cars.Count());               
}



Che banalmente visualizza il numero di auto (Cars) presenti nel  repository, ne aggiunge una e riesegue la conta delle auto registrate. Se volessimo analizzare l’SQL generato un ottimo strumento è sicuramete il SQL Profiler di SQL Server (che non dovrebbe mai mancare quando si lavora con un ORM  ), ma se utilizziamo EF6, ed il nostro obiettivo è semplicemente “scoprire\loggare” l’SQL generato da EF, possiamo modificare il codice precedente aggiungendo dopo la definizione del DbContext, la riga seguente:

 db.Database.Log = Console.Write;

 

Dove la proprietà Log è cosi’ definita:

public Action&amp;lt;string&amp;gt; Log { get; set; }

 


Eseguendo il codice della nostra applicazione dovremmo ottenere una “Console” simile alla seguente:



Di default il log è molto chiaro in quanto ci restituisce il testo SQL del comando, quando è stato eseguito, il tempo impiegato, il tipo di risultato, gli eventuali parametri ed il tipo corrispondente. Possiamo ovviamente cambiare il contenuto e la formattazione del log secondo le nostre esigenze (e non solo) come vedremo piu’ avanti. Per come è definita la proprietà Log, qualsiasi funzione che accetta una stringa puo’ essere utilizzata per scrivere il nostro log. Quindi potremmo utilizzare un metodo tipo il seguente:

public static void Log(string sql)
{
    Console.WriteLine("------------------------------------");
    Console.WriteLine("SQL LOG: {0} ", sql);
    Console.WriteLine("------------------------------------");            
}


 

oppure:

System.IO.StreamWriter streamWriter = new System.IO.StreamWriter (fileStream, System.Text.ASCIIEncoding.ASCII );
db.Database.Log = sql =&amp;gt; streamWriter.Write(sql);


 

Per scrivere il log direttamente su file. Il concetto dovrebbe essere abbastanza chiaro. Vediamo come personalizzare la formattazione del log. 

Database.Log non fa altro che utilizzare un ogetto DatabaseLogFormatter che a sua volta implementa le interfacce IDbCommandInterceptor e IDbInterceptor che sono rispettivamente l’interfaccia che permette di registrare un oggetto che possa ricevere notifiche da parte di Entity Framework quando un comando viene eseguito e l’interfaccia base per tutte le interfacce che permettono di fornire un Interception Point per differenti tipi di operazione.



Quindi, per creare il nostro “Formattatore Custom” non ci resta che ereditare dalla classe DatabaseLogFormatter ed eseguire l’override dei metodi che ci interessano, come nel caso seguente:

public class CustomLogFormatter
    : DatabaseLogFormatter
{
    public CustomLogFormatter(DbContext context, Action&amp;lt;string&amp;gt; writeAction)
        : base(context, writeAction)
    {
    }

    public override void LogCommand&amp;lt;TResult&amp;gt;(
        DbCommand command, DbCommandInterceptionContext&amp;lt;TResult&amp;gt; interceptionContext)
    {
        Write(string.Format("{0}{1}", "===============================================", Environment.NewLine));

        Write(string.Format(
            "Context{2}{0}{2}Command{2}{1}{2}",
            Context.GetType().Name,
            command.CommandText.Replace(Environment.NewLine, ""),
            Environment.NewLine));

        Write(string.Format("{0}{1}", "===============================================", Environment.NewLine));            
    }
}


 

Dove, l’override del metodo LogCommand esegue la formattazione del comando prima che questo sia eseguito da Entity Framework. LogCommand a sua volta  chiama eventualmente il metodo LogParameter per ogni parametro del comando, è necessario eseguire l’override di LogParameter per “customizzare” la formattazione del log dei paramateri. Infine, se vogliamo cambiare la formattazione del risultato, è necessario effettuare l’override di LogResult. Per interrompere l’esecuzione del comando, possiamo utilizzare il metodo :

interceptionContext.SuppressExecution()

 


Nel corpo dell’override di LogCommand. Per vedere in “funzione” il nostro “Formatter” è sufficiente registrare l’istanza di CustomLogFormatter tramite una classe derivata da DbConfiguration presente nello stesso assembly che contiene la definizione del DbContext:

public class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration()
    {
        SetDatabaseLogFormatter(
            (context, writeAction) =&amp;gt; new CustomLogFormatter(context, writeAction));
    }
}


Eseguendo, otteniamo il “nostro” log:



Per approfondimenti:

Entity Framework Codeplex

One Unicorn: EF6 SQL Logging&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101658.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/09/04/ef-6-logging-amp-interception.aspx</guid>
            <pubDate>Wed, 04 Sep 2013 15:15:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/09/04/ef-6-logging-amp-interception.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101658.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101658.aspx</trackback:ping>
        </item>
        <item>
            <title>OCA, Sync Framework e SQL Server 2008</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/08/21/oca-e-sync-framework-e-sql-server-2008.aspx</link>
            <description>   Ultimamente mi sono trovato a sviluppare un’applicazione con la necessità di sincronizzare i dati locali con un’istanza di SQL Server 2008. Generalmente parlando, le applicazioni OCA (occasionally connected application) permettono di utilizzare un’applicazione client che fa uso di dati memorizzati in una base di dati locale che periodicamente è sincronizzata  con un database centrale disposto su un server.  Il processo di sincronizzazione non è mai stato un task banale (almeno nel caso bidirezionale), è penso che ognuno di noi, almeno una volta nella vita da sviluppatore si sia imbattuto in questo tipo di operazione. Fino a qualche tempo fa, spesso si creavano soluzioni ad hoc, funzionanti, ma magari non performanti o comunque a basso riuso. Per fortuna (tra l’altro da diverso tempo ) abbiamo a disposizione il  Microsoft Sync Framework (che personalmente, fino ad oggi non ho mai avuto occasione di utilizzare in modo proficuo), una piattaforma  che fornisce agli sviluppatori gli strumenti necessari per aggiungere funzionalità di sincronizzazione ad applicazioni, servizi e dispositivi. Nello specifico del post,  ci concentreremo sul funzionamento relativo alla sincronizzazione di database, ma il Microsoft Sync Framework mette a disposizione i Synchronization Services per File Systems ed i Synchronization Services per FeedSync. La versione presente in Visual Studio 2010 è la 2.1, ma è possibile scaricare la versione 4.0 CTP , costruita sulla versione 2.1, con supporto al protocollo   “OData + Sync” per lo sviluppo più facile di applicazioni OCA su qualsiasi piattaforma capace di eseguire il caching dei dati oltre alla sincronizzazione di dati memorizzati su SQL Server o SQL Azure.  Durante il processo di sincronizzazione l’aspetto più complesso è sicuramente la tracciatura dei cambiamenti (ovvero i relativi INSERT, UPDATE e DELETE eseguiti sul database Client e\o Server), altrimenti, ogni volta che l’utente si collega al database centrale per la sincronizzazione dei dati deve necessariamente eseguire il download di tutte le informazioni  (in situazioni di connessioni lente o non affidabili potrebbe essere un problema di costi e\o tempi). Un metodo naive per eseguire il tracking dei cambiamenti è l’utilizzo di trigger o l’utilizzo di campi rowversion aggiunte alle tabelle soggette a sincronizzazione. Per la cancellazione dei record il discorso è leggermente diverso in quanto è necessario memorizzare le informazioni in una tabella separata (tombstone table) . Ovviamente, questa “metodologia” comporta alcuni svantaggi:     - E’ necessario introdurre modifiche allo schema della base di dati     - I trigger comportano problemi di performance    - Scrittura della logica per rowversion e cancellazione delle righe   Se utilizziamo SQL Server 2008 come database centrale, possiamo evitare i problemi precedentemente esposti in quanto in questa versione è stata introdotto il “SQL Server 2008 Change Tracking”, un meccanismo il cui utilizzo si “riduce” a marcare le tabelle da monitorare,  tracciando automaticamente le varie INSERT, UPDATE e DELETE, così da fornire gli opportuni cambiamenti ai client che richiedono di sincronizzarsi rispetto all’ultima operazione di sincronizzazione. Utilizzando il Sync Framework abbiamo questo supporto in modo nativo ed integrato in Visual Studio 2010 senza apportare modifiche allo schema del database, senza trigger e senza dover scrivere codice SQL di logica (maggiori dettagli su MSDN).   Proviamo a chiarire i concetti esposti con un esempio. Prendiamo in considerazione un database con un schema del tipo in figura:    Che descrive un semplicissimo database di un possibile e-commerce (Cliente, Acquisto e Prodotto). Il nostro scopo è sincronizzare i dati tra un client (una piccola applicazione stand-alone di esempio) che utilizza una database locale di SQL Server Compact 3.5 (od eventualmente 4.0 con le apposite modifiche) ed il database centrale presente in un’istanza di SQL Server 2008.  Creiamo un nuovo progetto Console o Windows Form (nel nostro caso) di Visual Studio 2010 a cui andiamo ad aggiungere il necessario per fornire l’accesso alla sincronizzazione dei dati. Dopo la creazione del progetto, aggiungiamo un nuovo item (dalla sezione Data) “Local Database Cache”:    A questo punto verrà visualizzata una nuova finestra nella quale andremo a specificare i parametri di connessione lato server e lato client:    Se  stiamo utilizzando una connessione verso un database di SQL Server 2008, il Check “User SQL Server change Tracking” dovrebbe essere abilitato, e spuntando la voce, abbiamo la possibilità di sfruttare il Change Tracking integrato. Ancora, possiamo scegliere se l’operazione di sincronizzazione avverrà all’interno di un’unica transazione (se vogliamo che tutti  o nessuno dei dati siano scaricati) oppure (secondo dello scenario)  se vogliamo scaricare\caricare ad ogni sincronizzazione quanti più dati possibili. Restando nella finestra, sono presenti delle liste a discesa che permettono di scegliere, all’interno della nostra soluzione di Visual Studio il progetto lato client ed il progetto lato server. Nel nostro caso lasciamo la voce selezionata di Default, e quindi consideriamo il progetto precedentemente creato. E’ arrivato il momento di scegliere le tabelle che faranno parte della nostra cache di dati locale: l’operazione è molto semplice in quanto è sufficiente utilizzare il bottone con la dicitura Add  in fondo a sinistra della ListBox presente:     Nella finestra “Configure Tables for Offline Use” è possibile selezionare le tabelle che vogliamo sincronizzare con i nostri client. Per ognuna di essa possiamo scegliere se ogni volta vogliamo scaricare l’interno contenuto della tabella (come durante la prima sincronizzazione)  o se  ogni successiva sincronizzazione sial di tipo incrementale. Nel caso stessimo utilizzando una versione diversa da SQL Server 2008 (ad esempio SQL Server 2005) come database centrale, non avendo a disposizione il supporto nativo al Change Tracking avremmo dovuto  specificare delle Stored Procedure ad-hoc nei campi Compare update using, Compare insert using e Move deleted items to a supporto della logica di sincronizzazione:    A questo punto il gioco è quasi finito, in quanto premendo su OK, al progetto verranno aggiunti tutti i file e riferimenti necessari al funzionamento. Piccola nota: nella schermata precedente premendo il link Show Code Example viene visualizzata una finestra di dialogo con del codice di esempio (molto comodo se si utilizza il Sync Framework per la prima volta) per effettuare la sincronizzazione dei dati:    A questo punto viene avviata la prima sincronizzazione con la creazione del file “.sdf” di SQL Server Compact (ricordiamo per default nella versione 3.5).  Dopo qualche secondo è visualizzata una nuova schermata in cui possiamo scegliere se utilizzare un DataSet o un file EDM (Entity Data Model) per il nostro Object Model as Data Model. Partiamo con un semplice DataSet (  ):    Nelle schermate che si susseguono andiamo a configurare il nostro DataSet  tipizzato con tutte le tabelle che servono al funzionamento della nostra applicazione client. Notiamo che oltre alle tabelle originali troviamo tre tabelle __syncArticles, _syncSubscriptions e __syncTransactioncs necessarie per le operazioni di sincronizzazione, ma possiamo tranquillamente ignorarle. Alla fine del Wizard, il nostro DataSet dovrebbe assomigliare a qualcosa di questo tipo:    Bene. Supponendo di aver aggiunto alla nostra soluzione una Windows Form contenente una griglia e due bottoni (Synchronize e Close) come nella figura seguente:    Nell’handler dell’evento click del bottone Synchronize possiamo scrivere del codice tipo:     LocalCacheSyncAgent syncAgent = new LocalCacheSyncAgent();syncAgent.Product.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;Microsoft.Synchronization.Data.SyncStatistics syncStats = syncAgent.Synchronize();////Server -&amp;gt; ClientStringBuilder sb = new StringBuilder();sb.AppendLine(string.Format("Download Changes: {0}", syncStats.DownloadChangesApplied));sb.AppendLine(string.Format("Download Failed: {0}", syncStats.DownloadChangesFailed));sb.AppendLine(string.Format("Upload Changes: {0}", syncStats.UploadChangesApplied));sb.AppendLine(string.Format("Upload Failed: {0}", syncStats.UploadChangesFailed));sb.AppendLine(string.Format("Start Time: {0}", syncStats.SyncStartTime));sb.AppendLine(string.Format("Complete Time: {0}", syncStats.SyncCompleteTime));MessageBox.Show(sb.ToString());


Dove come prima operazione creiamo un’istanza di LocalCacheSyncAgent, ovvero l’engine che si occuperà di effettuare materialmente il lavoro di sincronizzazione. Impostiamo tramite la proprietà SyncDirection una sincronizzazione di tipo Bidirezionale per la tabella Product. Altre possibili opzioni sono:


  - Download, sincronizzazione unidirezionale Server –&amp;gt; Client 

  - Upload, sincronizzazione unidirezionale Client –&amp;gt; Server 

  - Snapshot, durante la sincronizzazione viene scaricato un insieme di dati,  aggiornato completamente ad ogni sincronizzazione. 


A questo punto non resta che invocare il metodo Synchronize del nostro “Agent” che restituisce un’istanza di SyncStatistics contenente le informazioni sull’esito della sincronizzazione, che “raccogliamo” mediante uno StringBuilder e mostriamo all’utente al termine delle operazioni con una semplice MessageBox:



Sopra è mostrato il risultato della prima sincronizzazione. Aggiungendo una riga in Product nella tabella locale (client), e sincronizzando nuovamente dovremmo ottenere un risultato di questo tipo:



Dove chiaramente si evince come sia stato eseguito l’upload di dati verso il server. Ok, ma ovviamente non tutte le tabelle escono col buco, di conseguenza bisogna prepararsi ad ogni evenienza, ovvero alla gestione di possibili conflitti tra dati presenti su Client e Server durante la sincronizzazione. Modifichiamo la parte iniziale del codice precedente in questo modo:


  LocalCacheSyncAgent syncAgent = new LocalCacheSyncAgent();syncAgent.Product.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;////-----LocalCacheClientSyncProvider localProvider = syncAgent.LocalProvider as LocalCacheClientSyncProvider;LocalCacheServerSyncProvider serverProvider = syncAgent.RemoteProvider as LocalCacheServerSyncProvider;localProvider.ApplyChangeFailed += new EventHandler&amp;lt;Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs&amp;gt;(localProvider_ApplyChangeFailed);serverProvider.ApplyChangeFailed += new EventHandler&amp;lt;Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs&amp;gt;(serverProvider_ApplyChangeFailed);////-----Microsoft.Synchronization.Data.SyncStatistics syncStats = syncAgent.Synchronize();...


Dove attraverso istanze di LocalCacheClientSyncProvider e LocalCacheServerSyncProvicer ci sottoscriviamo agli eventi per la gestione dei conflitti, ApplyChangedFailed:


  if(e.Conflict.ConflictType == Microsoft.Synchronization.Data.ConflictType.ClientInsertServerInsert){    DataTable clientChange = e.Conflict.ClientChange;    DataTable serverChange = e.Conflict.ServerChange;    FrmConflicts frmConflicts = new FrmConflicts();    frmConflicts.SetDataSource(clientChange, serverChange);    frmConflicts.ShowDialog(this);    e.Action = Microsoft.Synchronization.Data.ApplyAction.RetryWithForceWrite;}if (e.Conflict.ConflictType == Microsoft.Synchronization.Data.ConflictType.ErrorsOccurred){    MessageBox.Show(e.Conflict.ErrorMessage);    e.Action = Microsoft.Synchronization.Data.ApplyAction.Continue;}


Nel codice intercettiamo due dei possibili conflitti che possono verificarsi: nel caso di conflitto dovuto ad  Insert su Client e Server (ad esempio su client e server viene aggiunto uno stesso prodotto), mostriamo all’utente tramite una seconda Windows Form (FrmConflicts) il dati che creano il problema , e dopo forziamo la scrittura (causando di fatto una duplicazione dei valori all’interno della tabella Product, ovviamente possono\devono essere considerate altre strategie scelte eventualmente dall’utente). Nel caso di conflitto dovuto ad errore non predicibile mostriamo (in modo molto brutale ) un MessageBox contenente informazioni di errore (in un’applicazione reale questo dovrebbe essere evitato in quanto potrebbero essere visualizzate informazioni sensibili per la sicurezza del sistema) e tentiamo di continuare la sincronizzazione dei dati.

Se invece di utilizzare un DataSet volessimo utilizzare Entity Framework, il gioco è semplice, basta utilizzare il Wizard dell’Entity Data Model per costruire un modello da un database già presente (il file .sdf) . Nello specifico caso, avremmo qualcosa di questo tipo:



Le operazioni di sincronizzazione a questo punto non sono più un problema (o almeno si spera ).&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100287.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/08/21/oca-e-sync-framework-e-sql-server-2008.aspx</guid>
            <pubDate>Sun, 21 Aug 2011 14:08:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/08/21/oca-e-sync-framework-e-sql-server-2008.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100287.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100287.aspx</trackback:ping>
        </item>
        <item>
            <title>The setup failed to read IIsMimeMap table&amp;hellip;</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2009/01/11/the-setup-failed-to-read-iismimemap-tablehellip.aspx</link>
            <description>Finalmente sono riuscito a ritagliare del tempo per formattare e ripristinare il mio portatile, prima che arrivi il mio periodo “caldo” (causa lavoro e Università). In questi giorni, mi è capitato di dover rimuovere da un PC, SQL Server 2005, nel caso in cui durante il processo di disinstallazione si presenti il messaggio : Il programma di installazione non riesce a leggere tabella IIsMimeMap. Il codice di errore è-2147024893 (o The setup failed to read IIsMimeMap table. The error code is –2147024893 )
 
la soluzione è in questo articolo, in pratica si tratta di disabilitare in sequenza i servizi Servizio  di Amministrazione di IIS e Servizio Pubblicazione sul Web prima di procedere con la disinstallazione &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/95167.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2009/01/11/the-setup-failed-to-read-iismimemap-tablehellip.aspx</guid>
            <pubDate>Sun, 11 Jan 2009 21:34:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2009/01/11/the-setup-failed-to-read-iismimemap-tablehellip.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/95167.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/95167.aspx</trackback:ping>
        </item>
        <item>
            <title>The database principal...and cannot be dropped</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2008/08/18/93739.aspx</link>
            <description>Promemoria. Questo link presenta una possibile soluzione nel caso in cui, lavorando con SQL Server 2005, si presenti il seguente messaggio d'errore:  The database principal owns a schema in the database, and cannot be dropped. (Microsoft SQL Server, Error: 15138). &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/93739.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2008/08/18/93739.aspx</guid>
            <pubDate>Mon, 18 Aug 2008 14:29:39 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2008/08/18/93739.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/93739.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/93739.aspx</trackback:ping>
        </item>
        <item>
            <title>Trigger SQL</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2007/11/25/89927.aspx</link>
            <description>Creazione di un trigger su tabella SQL Server. Post a titolo di promemoria. :-)
Codice per la creazione della tabella di esempio

CREATE TABLE [dbo].[Utenti](    [Utente_ID] [int] IDENTITY(1,1) NOT NULL,    [Utente_Cognome] [varchar](20) NOT NULL,    [Utente_Nome] [varchar](20) NOT NULL,    [Utente_Piano] [int] NULL,    [Utente_Telefono] [varchar](15) NULL,    [Utente_Email] [varchar](50) NULL, CONSTRAINT [PK_Utenti] PRIMARY KEY CLUSTERED (    [Utente_ID] ASC ) ON [PRIMARY] ) ON [PRIMARY]

Codice per la creazione del trigger

-- Crea un trigger per l'inserimento e l'aggiornamento. -- Viene recuperato il valore del campo [Utente_Cognome] inserito o aggiornato CREATE TRIGGER [Aggiorna] ON  [Utenti] AFTER INSERT,UPDATE AS BEGIN    DECLARE @Cognome varchar(20 ) SET @Cognome =(SELECT inserted.[Utente_Cognome] FROM inserted) EXECUTE TestTrigger @Cognome END

Codice per la Stored Procedure di Test
 

-- Modifica il valore del campo [Utente_Cognome] in 'Nuovo Cognome' CREATE PROCEDURE [TestTrigger] @Utente_Cognome varchar(50) AS UPDATE Utenti SET  Utente_Nome = 'Nuovo Cognome' WHERE Utente_Cognome =@Utente_Cognome 

La combinazione trigger/stored procedure  in questo caso è veramente insignificante, ma in realtà si potrebbero eseguire calcoli,recupero di dati, operazioni di verifica etc...
 
Technorati Tag: Trigger&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/89927.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2007/11/25/89927.aspx</guid>
            <pubDate>Sun, 25 Nov 2007 21:34:19 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2007/11/25/89927.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/89927.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/89927.aspx</trackback:ping>
        </item>
    </channel>
</rss>