{"id":3612,"date":"2021-09-06T12:00:09","date_gmt":"2021-09-06T12:00:09","guid":{"rendered":"https:\/\/cloudsurfers.it\/?p=3612"},"modified":"2021-09-06T12:00:14","modified_gmt":"2021-09-06T12:00:14","slug":"azure-functions-entity-framework","status":"publish","type":"post","link":"https:\/\/cloudsurfers.it\/index.php\/azure-functions-entity-framework\/","title":{"rendered":"Azure Functions + Entity Framework"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"682\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/articolo_1-1024x682.jpg\" alt=\"\" class=\"wp-image-3613\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/articolo_1-1024x682.jpg 1024w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/articolo_1-300x200.jpg 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/articolo_1-768x511.jpg 768w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/articolo_1-600x400.jpg 600w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/articolo_1.jpg 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In questa guida vedremo come imbastire un piccolo progetto <strong>.NET Core Azure Functions<\/strong> che interroghi una base dati <strong>SQL Server<\/strong> utilizzando lo strumento <strong>Entity Framework<\/strong> per l&#8217;interrogazione.<\/p>\n\n\n\n<p>Prima per\u00f2 un piccolo accenno di teoria.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Che cos&#8217;\u00e8 Azure Functions?<\/h3>\n\n\n\n<p>Citando la documentazione ufficiale <em>Microsoft<\/em>, <strong>Azure Functions<\/strong> \u00e8 una soluzione <em>serverless <\/em>(priva di server) che permette di scrivere poco codice di programmazione, mantenendo il minimo di infrastruttura server e risparmiando cos\u00ec costi.<\/p>\n\n\n\n<p>In sostanza, chi utilizza <em>Azure Functions<\/em> si occupa solo della mera parte di programmazione, il resto, per esempio la preparazione dell&#8217;hardware, l&#8217;aggiornamento software e\/o il mantenimento in esecuzione del tutto, viene gestito dall&#8217;infrastruttura cloud <em>Azure<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Caso d&#8217;uso reale<\/h3>\n\n\n\n<p>Abbiamo bisogno di un processo, schedulato giornalmente, che si occupi del controllo di determinati record all&#8217;interno di una base dati accessibile in rete e, successivamente, al verificarsi di determinate condizioni sui record controllati, invii una e-mail di servizio ad un indirizzo preimpostato.<\/p>\n\n\n\n<p>Tradizionalmente, senza utilizzare <em>Azure Functions<\/em>, una volta terminata la fase di scrittura del codice della procedura sopra, lo sviluppatore si trover\u00e0 nella condizione di scegliere una strada per la pubblicazione del servizio: macchina fisica in rete 24 ore su 24 in ufficio, VPS a noleggio mensile di qualche provider, ecc&#8230; Successivamente dovr\u00e0 gestire la configurazione di tutta l&#8217;infrastruttura e la sua manutenibilit\u00e0 futura: aggiornamenti S.O., aggiornamenti hardware, ecc.\u2026 Tutti aspetti che influiscono sui tempi, sui costi e sul <em>know-how<\/em> di lavoro.<\/p>\n\n\n\n<p>Utilizzando <em>Azure Functions<\/em>, lo sviluppatore scrive il codice della funzione, pubblica su una risorsa <em>Azure<\/em> direttamente da <em>Visual S<\/em>tudio. La funzione \u00e8 in rete e funzionante nell&#8217;immediato.<\/p>\n\n\n\n<p>Vediamo ora i passaggi per ottenere questa immediatezza.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Requisiti<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li><strong><a href=\"https:\/\/visualstudio.microsoft.com\/it\/downloads\/\" target=\"_blank\" rel=\"noreferrer noopener\">Visual Studio<\/a><\/strong> con gli <strong>strumenti Azure<\/strong> installati (<em>in questa guida viene utilizzata la versione 2019<\/em>);<\/li><li><strong><a href=\"https:\/\/www.microsoft.com\/it-it\/sql-server\/sql-server-downloads\" target=\"_blank\" rel=\"noreferrer noopener\">SQL Server<\/a><\/strong> per la base dati (<em>in questa guida viene utilizzata la versione Express 2019<\/em>).<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Il progetto di esempio<\/h3>\n\n\n\n<p>Ricapitolando, data una base di dati con informazioni anagrafiche, la funzione <em>Azure <\/em>che scriveremo dovr\u00e0 processare tutte le anagrafiche inserite non ancora processate e, successivamente, impostarle come processate utilizzando un campo di <em>FLAG <\/em>che chiameremo <strong>Readed<\/strong>.<\/p>\n\n\n\n<p>Creiamo quindi un nuovo database, nel nostro caso <strong>azure_function_example<\/strong>, ed una nuova tabella, <strong>Users<\/strong>, con al suo interno quattro campi:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Id <\/strong>&#8211; UNIQUEIDENTIFIER &#8211; NOT NULL &#8211; PRIMARY KEY<\/li><li><strong>FirstName <\/strong>&#8211; NVARCHAR(MAX) &#8211; NOT NULL<\/li><li><strong>LastName <\/strong>&#8211; NVARCHAR(MAX) &#8211; NOT NULL<\/li><li><strong>Readed <\/strong>&#8211; BIT &#8211; NOT NULL &#8211; DEFAULT 0<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE &#91;dbo].&#91;Users](\n\t&#91;Id] &#91;uniqueidentifier] NOT NULL,\n\t&#91;FirstName] &#91;nvarchar](max) NOT NULL,\n\t&#91;LastName] &#91;nvarchar](max) NOT NULL,\n\t&#91;Readed] &#91;bit] NOT NULL,\n CONSTRAINT &#91;PK_Users] PRIMARY KEY CLUSTERED \n(\n\t&#91;Id] ASC\n)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON &#91;PRIMARY]\n) ON &#91;PRIMARY] TEXTIMAGE_ON &#91;PRIMARY]\nGO\n\nALTER TABLE &#91;dbo].&#91;Users] ADD  CONSTRAINT &#91;DF_Users_Readed]  DEFAULT ((0)) FOR &#91;Readed]\nGO\n<\/code><\/pre>\n\n\n\n<p>Popoliamo la tabella con qualche record di esempio, impostando per tutti il campo <em>FLAG<\/em> <strong>Readed <\/strong>a <em>FALSE <\/em>(0):<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Id<\/strong><\/td><td><strong>FirstName<\/strong><\/td><td><strong>LastName<\/strong><\/td><td><strong>Readed<\/strong><\/td><\/tr><tr><td>8530B138-5F43-437F-8854-268E5D2E1C50<\/td><td>Paolo<\/td><td>Gialli<\/td><td>0<\/td><\/tr><tr><td>4794C833-F277-419D-BECA-5E59D3DF9AE2<\/td><td>Antonio<\/td><td>Verdi<\/td><td>0<\/td><\/tr><tr><td>80405F8B-651B-438B-A8C2-B7B82E8E78CA<\/td><td>Mario<\/td><td>Rossi<\/td><td>0<\/td><\/tr><tr><td>323C2A9A-5BEF-4EB3-A951-D40533B74A01<\/td><td>Stefano<\/td><td>Bianchi<\/td><td>0<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><em>Nota: gli identificativi univoci sono stati generati casualmente utilizzando lo strumento <a href=\"https:\/\/www.guidgenerator.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.guidgenerator.com\/<\/a>.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">La funzione<\/h3>\n\n\n\n<p>Proseguiamo ora con la creazione del progetto <em>.NET<\/em>. Apriamo <strong>Visual Studio<\/strong> ed all&#8217;interno della procedura guidata di creazione di un nuovo progetto, selezioniamo la voce &#8220;<strong>Funzioni di Azure<\/strong>&#8220;:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"180\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure1.png\" alt=\"\" class=\"wp-image-3624\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure1.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure1-300x84.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure1-640x180.png 640w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure1-600x168.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p><em><span class=\"has-inline-color has-vivid-red-color\">Nota: la voce non \u00e8 presente se durante l&#8217;installazione di Visual Studio non vengono installati anche gli strumenti Azure.<\/span><\/em><\/p>\n\n\n\n<p>Successivamente, eseguiamo la configurazione di base del progetto:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"266\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure2.png\" alt=\"\" class=\"wp-image-3625\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure2.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure2-300x124.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure2-640x266.png 640w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure2-600x248.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"445\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure3.png\" alt=\"\" class=\"wp-image-3626\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure3.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure3-300x208.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure3-600x415.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p>Selezioniamo dal menu a discesa (schermata superiore) &#8220;<strong>Funzioni di Azure v3 (.NET Core)<\/strong>&#8220;. <strong>Timer trigger<\/strong> per eseguire la funzione in modalit\u00e0 schedulata ed impostiamo, nella casella a sinistra dell&#8217;elenco, l&#8217;espressione <em>NCRONTAB <\/em>&#8220;<strong>30 * * * * *<\/strong>&#8221; per indicarne le regole di schedulazione. In questo caso la funzione verr\u00e0 eseguita il trentesimo secondo di ogni minuto, di ogni ora, di ogni giorno, di ogni mese e di ogni anno.<\/p>\n\n\n\n<p>Nota: potete a<em>pprofondire la libreria NCronTab e le regole delle espressioni NCRONTAB al seguente indirizzo <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.microsoft.com\/it-it\/azure\/azure-functions\/functions-bindings-timer?tabs=csharp#ncrontab-expressions\" target=\"_blank\">https:\/\/docs.microsoft.com\/it-it\/azure\/azure-functions\/functions-bindings-timer?tabs=csharp#ncrontab-expressions<\/a>.<\/em><\/p>\n\n\n\n<p>Dopo aver creato il progetto verr\u00e0 aperta la funzione, chiamata <strong>Function1<\/strong> di default:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;FunctionName(\"Function1\")]\npublic static void Run(&#91;TimerTrigger(\"30 * * * * *\")]TimerInfo myTimer, ILogger log)\n{\n    log.LogInformation($\"C# Timer trigger function executed at: {DateTime.Now}\");\n}\n<\/code><\/pre>\n\n\n\n<p>Eseguendo il codice, otteniamo il seguente risultato:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"273\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure4.png\" alt=\"\" class=\"wp-image-3628\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure4.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure4-300x127.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure4-640x273.png 640w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure4-600x255.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p>Come da schedulazione, il trentesimo secondo di ogni minuto viene stampato sul terminale il metodo <strong>LogInformation <\/strong>richiamano dalla funzione. Possiamo notare come il log, molto dettagliato, ci fornisce in autonomia anche l&#8217;indicazione del tempo di esecuzione della funzione ed il suo nome, nel caso c&#8217;\u00e8 ne sia presente pi\u00f9 di una per esempio.<\/p>\n\n\n\n<p>Aggiungiamo ora al progetto i pacchetti <strong>EntityFramework <\/strong>necessari dal gestore di pacchetti <em>NuGet<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"182\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure5.png\" alt=\"\" class=\"wp-image-3629\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure5.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure5-300x85.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure5-640x182.png 640w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure5-600x170.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p><strong><em><span class=\"has-inline-color has-vivid-red-color\">Nota: Azure Functions v3 utilizza .NET Core 3.1, \u00e8 importantissimo quindi installare EntityFrameworkCore.SqlServer 3.1.x e non l&#8217;ultima versione 5 disponibile per motivi di compatibilit\u00e0 con alcune librerie referenziate di EntityFramework non compatibili con  la versione .NET Core del progetto.<\/span><\/em><\/strong><\/p>\n\n\n\n<p>Installiamo anche <strong>EntityFramworkCore.Tools<\/strong> per poter utilizzare il comando <strong>Scaffold-DbContext<\/strong> per generare automamente la classe di <em>Context <\/em>e i modelli della base dati creata in precedenza.<\/p>\n\n\n\n<p>Posizioniamoci quindi all&#8217;interno della &#8220;<strong>Console di Gestione pacchetti<\/strong>&#8221; e lanciamo il comando per eseguire lo <em>Scaffold<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Scaffold-DbContext \"Data Source=SERVER_SQL;Initial Catalog=azure_function_example;Integrated Security=True;\" Microsoft.EntityFrameworkCore.SqlServer -Context ExampleContext -OutputDir Models -Force<\/code><\/pre>\n\n\n\n<p>Al termine dell&#8217;esecuzione della procedura, verr\u00e0 creata una nuova cartella <strong>Models<\/strong> all&#8217;interno della cartella principale del progetto, con all&#8217;interno il file <strong>Users.cs<\/strong> che identifica il modello della tabella <strong>Users <\/strong>della base dati:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public partial class Users\n{\n    public Guid Id { get; set; }\n    public string FirstName { get; set; }\n    public string LastName { get; set; }\n    public bool Readed { get; set; }\n}\n<\/code><\/pre>\n\n\n\n<p>All&#8217;interno della cartella<strong> <\/strong>viene creato anche il file E<strong>xampleContext.cs <\/strong>(E<em>xampleContext perch\u00e8 indicato all&#8217;interno del comando di Scaffold)<\/em> che fornisce il C<em>ontext p<\/em>er collegarsi ed effettuare operazioni sul database.<\/p>\n\n\n\n<p>Torniamo ora alla funzione <strong>Function1<\/strong> ed apportiamo le modifiche al codice come segue:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;FunctionName(\"Function1\")]\npublic static void Run(&#91;TimerTrigger(\"30 * * * * *\")]TimerInfo myTimer, ILogger log)\n{\n    using (var ctx = new ExampleContext())\n    {\n        var users = ctx.Users.Where(u =&gt; !u.Readed).ToList();\n        if(users.Count &gt; 0)\n        {\n            foreach (var user in users)\n            {\n                \/\/ process user...\n\n                \/\/ ...\n\n                \/\/ mark user as readed\n                user.Readed = true;\n                        \n                ctx.Users.Update(user);\n\n                log.LogInformation($\"User {user.FirstName} readed!\");\n            }\n\n            ctx.SaveChanges();\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Le modifiche apportate avviano una nuova istanza <strong>ExampleContext<\/strong> (<em>non impostando una stringa di connessione, viene utilizzata di default quella indicata all&#8217;interno del comando di Scaffold<\/em>), viene ottenuto successivamente l&#8217;elenco degli utenti con il campo <em>FLAG <\/em><strong>Readed <\/strong>impostata a <strong>FALSE <\/strong>e viene scorsa la lista ottenuta nel caso sia presente almeno un&#8217;utente.<\/p>\n\n\n\n<p>Ogni volta che un&#8217;utente viene processato, viene impostato il campo <em>FLAG <\/em><strong>Readed <\/strong>a <strong>TRUE<\/strong>.<\/p>\n\n\n\n<p>Lanciamo in esecuzione la funzione con le nuove modifiche apportate ed osserviamo il risultato:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"326\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure6.png\" alt=\"\" class=\"wp-image-3631\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure6.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure6-300x152.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure6-600x304.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p>Come si pu\u00f2 leggere dal log, nella prima esecuzione vengono processati tutti e quattro i record presenti nella base dati (<em>FLAG <\/em><strong>Readed <\/strong>a <strong>FALSE<\/strong>), nella seconda esecuzione invece non viene processato nulla.<\/p>\n\n\n\n<p>Dando uno sguardo alla base dati, successivamente all&#8217;esecuzione della funzione:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"122\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure7.png\" alt=\"\" class=\"wp-image-3632\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure7.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure7-300x57.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure7-640x122.png 640w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure7-600x114.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p>Tutti e quattro i record hanno il campo <em>FLAG <\/em><strong>Readed <\/strong>impostato a <strong>TRUE<\/strong>, correttamente processati dalla funzione.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusione<\/h3>\n\n\n\n<p>Come abbiamo visto, la creazione di una funzione schedulata periodicamente, che esegue operazioni su una base dati, \u00e8 molto semplice e veloce con l&#8217;utilizzo di <strong>Azure Functions<\/strong> e <strong>Visual Studio<\/strong>.<\/p>\n\n\n\n<p>Inoltre questo tipo di approccio semplifica anche l&#8217;eventuale pubblicazione futura su di una sottoscrizione <em>Azure <\/em>grazie alle procedure guidate di <em>Visual Studio<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"452\" src=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure8.png\" alt=\"\" class=\"wp-image-3633\" srcset=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure8.png 643w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure8-300x211.png 300w, https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/azure8-600x422.png 600w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<p>Senza ombra di dubbio la soluzione migliore per chi vuole spendere tutto il proprio tempo nella scrittura ed ottimizzazione del codice, senza pensare all&#8217;infrastruttura o ad altro.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Link Utili<\/h3>\n\n\n\n<p>Potete scaricare il progetto di esempio <a href=\"https:\/\/cloudsurfers.it\/wp-content\/uploads\/2021\/09\/FunctionAppExample.zip\">qui<\/a>.<\/p>\n\n\n\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-functions\/functions-overview\">https:\/\/docs.microsoft.com\/en-us\/azure\/azure-functions\/functions-overview<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In questa guida vedremo come imbastire un piccolo progetto .NET Core Azure Functions che interroghi una base dati SQL Server utilizzando lo strumento Entity Framework per l&#8217;interrogazione.<\/p>\n","protected":false},"author":3,"featured_media":3613,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wds_primary_category":0,"footnotes":""},"categories":[90,41,36,37],"tags":[43,164,163,166,140,165],"class_list":["post-3612","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-azure","category-guide","category-sql-server","tag-azure","tag-entityframework","tag-functions","tag-netcore","tag-sql","tag-sqlserver"],"_links":{"self":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts\/3612","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/comments?post=3612"}],"version-history":[{"count":0,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/posts\/3612\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/media\/3613"}],"wp:attachment":[{"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/media?parent=3612"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/categories?post=3612"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudsurfers.it\/index.php\/wp-json\/wp\/v2\/tags?post=3612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}