<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>WCF</title>
        <link>http://blogs.ugidotnet.org/PietroLibroBlog/category/WCF.aspx</link>
        <description>WCF</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>Modi diversi di recuperare il numero di messaggi in una coda MSMQ</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/01/28/modi-diversi-di-recuperare-il-numero-di-messaggi-in-una.aspx</link>
            <description>Ultimamente mi trovo a lavorare su di un progetto che utilizza WCF e MSMQ. Una delle classiche operazioni quando si lavora con queste tecnologie è sicuramente recuperare il numero di messaggi presenti in una coda. Tra documentazione e ricerche su internet, alla fine si “scopre” che ci sono diversi metodi per risolvere lo stesso problema:     Cursori di MSMQ     Utilizzo di GetAllMessages     Utilizzo di GetEnumerator2     PowerShell     Performance Counter    Traducendo il tutto in righe di codice, per il punto 1) abbiamo:  public int CountByCursor()
{
    int count = 0;
    Cursor cursor = _messageQueue.CreateCursor();
    Message m = CursorPeekWithoutTimeout(cursor, PeekAction.Current);
    if (m != null)
    {
        count = 1;
        while ((m = CursorPeekWithoutTimeout(cursor, PeekAction.Next)) != null)
        {
            count++;
        }
        if (m != null) m.Dispose();
    }
    cursor.Dispose();
    return count;
}

private Message CursorPeekWithoutTimeout(Cursor cursor, PeekAction action)
{
    Message ret = null;

    try
    {
        ret = _messageQueue.Peek(new TimeSpan(1), cursor, action);
    }
    catch (MessageQueueException mqe)
    {
        if (mqe.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
        {
            throw;
        }
    }
    return ret;
}


Sinceramente questo è il metodo che più non mi piace, sarà per la parola “Cursore”, sarà per la gestione dell’eccezione, sarà perchè la vedo poco pulita. 

Passiamo al punto 2):

 public int CountByGetAllMessages()
{
    return _messageQueue.GetAllMessages().Length;
}


Semplice e pulita, ma come vedremo a breve, le prestazioni scendono con l’aumentare dei messaggi in coda.

Punto 3), “GetMessageEnumerator2”:

var x = _messageQueue.GetMessageEnumerator2();
int counter = 0;
while (x.MoveNext())
{
    counter++;
}
return counter;

Sfruttiamo il MessageEnumerator ritornato dal metodo GetEnumerator2 ed iteriamo per spostare il cursore fino alla fine della coda.

Punto 4), “PowerShell” (in questo caso mi sono limitato a copiare del codice trovato in rete):

var path = string.Format(@"\\{0}\root\CIMv2", machine);

ManagementScope scope;

if (string.IsNullOrEmpty(username))
{
    scope = new ManagementScope(path);
}
else
{
    var options = new ConnectionOptions { Username = username, Password = password };
    scope = new ManagementScope(path, options);
}

scope.Connect();

if (queuePath.StartsWith(".\\")) queuePath = queuePath.Replace(".\\", string.Format("{0}\\", machine));

string queryString = String.Format("SELECT * FROM Win32_PerfFormattedData_msmq_MSMQQueue");
var query = new ObjectQuery(queryString);
var searcher = new ManagementObjectSearcher(scope, query);
IEnumerable&amp;lt;int&amp;gt; messageCountEnumerable =
    from ManagementObject queue in searcher.Get()
    select (int)(UInt64)queue.GetPropertyValue("MessagesInQueue");
var x = messageCountEnumerable.First();

return x;


ed infine il punto 5) “Performance Counter”:

System.Diagnostics.PerformanceCounter backupQueueCounter = new System.Diagnostics.PerformanceCounter(
    "MSMQ Queue", "Messages in Queue", "queue_path");

return backupQueueCounter.NextValue();


Bene, ora quale usare ? Proviamo con un piccolo test: ad una coda privata aggiungiamo 10.000 messaggi per volta (all’interno di un ciclo) e proviamo ad utilizzare i metodi su descritti per recuperare il numero di messaggi presenti in coda (si suppone che tra un conteggio e l’altro nella coda non vengano aggiunti altri messaggi). Iteriamo il procedimento per tre volte. 

Di seguito i risultati ottenuti (espressi in millisecondi, per le misure del tempo di esecuzione è stata utilizzata la classe System.Diagnostics.Stopwatcher):

Prima Iterazione


    
      #Msgs

      MSMQ Cursor

      GetAllMessages

      GetEnumerator2

      PowerShell

      Performance C.
    

    
      10.000

      449,816

      580,703

      36,37

      78,543

      351,86
    

    
      20.000

      928,18

      1.297,72

      78,16

      9,888

      0,462
    

    
      30.000

      1.340,44

      1.854,52

      137,82

      10,563

      1,121
    

    
      40.000

      1.769,73

      2.656,28

      194,652

      12,061

      3,187
    

    
      50.000

      2.188,74

      3.427,84

      190,672

      10,739

      0,452
    

    
      60.000

      2.631,29

      3.909,71

      231,995

      10,219

      0,364
    

    
      70.000

      3.006,52

      4.771,09

      264,112

      5.802,42

      0,462
    

    
      80.000

      3.469,49

      6.116,47

      309,691

      10,075

      0,545
    

    
      90.000

      4.000,00

      6.134,66

      372,885

      9,876

      0,435
    

    
      100.000

      4.544,33

      6.932,08

      424,196

      9,024

      0,41
    
  
 

Seconda Iterazione


    
      #Msgs

      MSMQ Cursor

      GetAllMessages

      GetEnumerator2

      PowerShell

      Performance C.
    

    
      10.000

      475,357

      609,866

      38,022

      285,978

      351,955
    

    
      20.000

      912,591

      1.315,49

      76,912

      10,453

      0,502
    

    
      30.000

      1.417,26

      2.066,92

      122,745

      11,156

      0,366
    

    
      40.000

      1.901,66

      2.718,64

      153,373

      9,947

      0,349
    

    
      50.000

      2.393,97

      3.386,43

      203,553

      10,962

      0,358
    

    
      60.000

      2.659,28

      4.546,84

      280,257

      9,832

      0,413
    

    
      70.000

      3.246,77

      4.938,01

      278,404

      11,664

      0,517
    

    
      80.000

      3.718,89

      5.881,67

      330,857

      13,688

      0,506
    

    
      90.000

      4.230,99

      6.677,00

      362,374

      10,155

      0,508
    

    
      100.000

      4.832,89

      7.585,19

      464,216

      16,495

      0,681
    
  
 

Terza Iterazione


    
      #Msgs

      MSMQ Cursor

      GetAllMessages

      GetEnumerator2

      PowerShell

      Performance C.
    

    
      10.000

      533,294

      621,392

      41,496

      79,286

      376,431
    

    
      20.000

      911,513

      1.338,41

      79,827

      9,354

      0,38
    

    
      30.000

      1.339,34

      2.123,46

      120,693

      12,969

      0,414
    

    
      40.000

      1.799,28

      2.658,01

      158,606

      9,423

      0,374
    

    
      50.000

      2.196,96

      3.221,87

      199,273

      10,413

      0,426
    

    
      60.000

      2.562,49

      4.140,15

      257,22

      8,81

      0,411
    

    
      70.000

      3.358,83

      4.715,56

      327,474

      14,808

      0,53
    

    
      80.000

      4.417,58

      6.690,44

      316,044

      17,334

      0,825
    

    
      90.000

      4.185,52

      6.229,67

      340,457

      11,773

      0,396
    

    
      100.000

      4.407,13

      6.658,46

      390,498

      12,944

      0,589
    
  
 

Dai risultati ottenuti si ottiene che l’utilizzo del “Performance Counter”, in caso di letture successive, sembrerebbe essere quello più efficiente. 

In attesa di altri giudizi ed approfondimenti :-).&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/101412.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/01/28/modi-diversi-di-recuperare-il-numero-di-messaggi-in-una.aspx</guid>
            <pubDate>Mon, 28 Jan 2013 13:13:32 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2013/01/28/modi-diversi-di-recuperare-il-numero-di-messaggi-in-una.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/101412.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/101412.aspx</trackback:ping>
        </item>
        <item>
            <title>DomusDotNet : We Want Web, grazie a tutti :-)</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx</link>
            <description>Ieri 9/3/12 si è svolto l’evento WeWantWeb organizzato da DomusDotNet presso la sede Microsoft di Roma. Le sessioni sono state registrare e quanto prima pubblicheremo Slide, codice sorgente degli esempi e Video, sul sito di DomusDotNet. Grazie a tutti i partecipanti!!! Attendiamo i vostri feedback! Al prossimo evento .    Da sinistra verso destra: Alessandro Mostarda e Massimo Bonanni, Giorgio Di Nardo, Nick, io , parte di coloro che hanno avuto la pazienza di ascoltarci .&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100854.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx</guid>
            <pubDate>Sat, 10 Mar 2012 20:52:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100854.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100854.aspx</trackback:ping>
        </item>
        <item>
            <title>DomusDotNet: We Want Web</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/02/12/domusdotnet-we-want-web.aspx</link>
            <description>Come da titolo, evento interamente dedicato al mondo del Web!!! A breve apriranno le iscrizioni. Iscrizioni aperte!!!    Tutti i dettagli e l’agenda completa sulla pagina dell’evento: WeWantWeb. &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100769.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/02/12/domusdotnet-we-want-web.aspx</guid>
            <pubDate>Sun, 12 Feb 2012 22:31:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/02/12/domusdotnet-we-want-web.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100769.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100769.aspx</trackback:ping>
        </item>
        <item>
            <title>DomusDotNet: WCF Data Services (Terza Parte)</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/25/domusdotnet-wcf-data-services-terza-parte.aspx</link>
            <description>Terzo ed ultimo articolo (qualcuno dirà finalmente ) della serie dedicata ai WCF Data Services. Articolo completo su DomusDotNet. Critiche, consigli e suggerimenti sono sempre ben accetti.&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100729.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/25/domusdotnet-wcf-data-services-terza-parte.aspx</guid>
            <pubDate>Wed, 25 Jan 2012 14:59:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/25/domusdotnet-wcf-data-services-terza-parte.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100729.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100729.aspx</trackback:ping>
        </item>
        <item>
            <title>OData T4 for C#</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/20/odata-t4-for-c.aspx</link>
            <description>Annuncio fresco fresco (quasi  ) da parte del WCF Data Services Team Blog : http://blogs.msdn.com/b/astoriateam/archive/2012/01/19/announcing-odata-t4-for-c-preview-1.aspx&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100715.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/20/odata-t4-for-c.aspx</guid>
            <pubDate>Fri, 20 Jan 2012 11:54:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/20/odata-t4-for-c.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100715.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100715.aspx</trackback:ping>
        </item>
        <item>
            <title>MCTS 70-513</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/17/mcts-70-513.aspx</link>
            <description>Ieri, anche questo è andato. E’ stata una bella soddisfazione. Ora avanti per l’MCPD . &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100707.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/17/mcts-70-513.aspx</guid>
            <pubDate>Tue, 17 Jan 2012 17:15:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/17/mcts-70-513.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100707.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100707.aspx</trackback:ping>
        </item>
        <item>
            <title>DomusDotNet: WCF Data Services (Seconda Parte)</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/11/domusdotnet-wcf-data-services-seconda-parte.aspx</link>
            <description>Secondo articolo della serie dedicata ai WCF Data Services: utilizzo con Entity Framework, ed approfondimento su Service Operations. Nel codice allegato un client ASP.NET MVC di test. Articolo completo sul sito di DomusDotNet. Al solito, consigli e suggerimenti sono sempre ben accetti .&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100692.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/11/domusdotnet-wcf-data-services-seconda-parte.aspx</guid>
            <pubDate>Wed, 11 Jan 2012 07:56:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2012/01/11/domusdotnet-wcf-data-services-seconda-parte.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100692.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100692.aspx</trackback:ping>
        </item>
        <item>
            <title>DomusDotNet: WCF Data Services (Prima parte)</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/21/domusdotnet-wcf-data-services-prima-parte.aspx</link>
            <description>Prima parte di una serie di articoli dedicati ai WCF Data Services, al protocollo OData e REST. Per gli interessati , articolo completo qui. &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100645.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/21/domusdotnet-wcf-data-services-prima-parte.aspx</guid>
            <pubDate>Wed, 21 Dec 2011 01:00:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/12/21/domusdotnet-wcf-data-services-prima-parte.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100645.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100645.aspx</trackback:ping>
        </item>
        <item>
            <title>WCF, netsh e &amp;ldquo;prenotazione&amp;rdquo; URL</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/08/22/wcf-netsh-e-ldquoprenotazionerdquo-url.aspx</link>
            <description>Post promemoria. Se abbiamo la necessità di eseguire l’hosting di un servizio WCF su Windows Vista, Windows Server 2008R2 o Windows 7 tramite ad esempio un’applicazione console (Windows Form o WPF ) è necessario eseguire una “prenotazione” dello spazio dei nomi URL per lo specifico account DOMAIN\User. Per eseguire questo scopo in modo programmatico (e non avere la necessità di creare un file d’installazione) allora possiamo scrivere del codice tipo:     string batContent = string.Format(@"netsh http add urlacl url=http://+:{0}/ user={1}\{2}",    uriToRegister.Port, Environment.MachineName, Environment.UserName);string batPath = "NetBat.bat";System.IO.File.WriteAllText(batPath, batContent);ProcessStartInfo startInfo = new ProcessStartInfo();startInfo.UseShellExecute = true;startInfo.Verb = "runas";startInfo.FileName = "cmd.exe";startInfo.Arguments = string.Format("/c {0}{1}{0}", (char)34, batPath);Process p = System.Diagnostics.Process.Start(startInfo);p.WaitForExit();


per la registrazione dello spazio dei nomi URL nell’urlacl dello specifico account DOMAIN\User. Possiamo utilizzare del codice tipo:


  string batContent = string.Format(@"netsh http delete urlacl url=http://+:{0}/ user={1}\{2}",     uriToUniregister.Port, Environment.MachineName, Environment.UserName);


per la rimozione. Il codice crea un file con estensione “.bat” eseguito tramite linea di comando. Ovviamente l’esecuzione del codice richiede l’elevazione dei privilegi dell’utente (se necessario). Il codice può essere utilizzato anche in caso di applicazioni ClickOnce. &lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100290.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/08/22/wcf-netsh-e-ldquoprenotazionerdquo-url.aspx</guid>
            <pubDate>Mon, 22 Aug 2011 23:08:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/08/22/wcf-netsh-e-ldquoprenotazionerdquo-url.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100290.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100290.aspx</trackback:ping>
        </item>
        <item>
            <title>WCF Data Service (CTP2) e EF 4.1</title>
            <link>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/05/15/wcf-data-service-ctp2-e-ef-4.1.aspx</link>
            <description>Chi usa i WCF Data Service (vedi ADO.NET Data Service), potrebbe incontrare qualche difficoltà nell’utilizzo di Entity Framework 4.1 utilizzando l’approccio Code First, “a causa” del DbContext, dato che un DataService&amp;lt;T&amp;gt; si aspetta  un T derivato da ObjectContext . “Under the hood” il DbContext utilizza ObjectContext e di conseguenza è facile immaginare una possibile soluzione al problema: eseguire l’ovveride del metodo CreateDataSource del DataService&amp;lt;T&amp;gt; ed utilizzare l’ObjectContext corrente. E’ sufficiente qualche ricerca tramite Bing o Google per trovare del codice di esempio. Per chi ha voglia di sperimentare, può a scaricare la versione WCF Data Service CTP 2 di Marzo 2011, per utilizzare il supporto “nativo” al DbContext. Il pacchetto d’installazione può essere scaricato qui: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=60fb0117-8cea-4359-b392-6b04cdc821be dove tra l’altro è presente un overview delle modifiche apportare rispetto alla versione precedente (altre info si trovano qui: http://blogs.msdn.com/b/writingdata_services/archive/2011/03/09/march-2011-ctp-of-wcf-data-services-for-odata-v3-is-live.aspx).  Per eseguire qualche test, partiamo da un’applicazione ASP.NET vuota, alla quale aggiungiamo una classe C# con la definizione del modello dati, una biblioteca, composta dalle entità “Book” ed “Author”, ogni “Author” ha una relazione one-to-many con “Book”. Tradotto in codice:          public class Book{    [Key]           public int Id { get; set; }    [Required]    [MaxLength (80)]    public string Title { get; set; }    [Required]    public string Summary { get; set; }}public class Author{    [Key]    public int Id { get; set; }    [Required]    public string Name { get; set; }    public virtual ICollection&amp;lt;Book&amp;gt; Books { get; set; }}

    
Generalmente preferisco utilizzare le Fluent API rispetto alle DateAnnotations, ma essendo un modello veramente semplice…va bene lo stesso . Definiamo il DbContext in questo modo:


  public class LibraryContext : DbContext{    public DbSet&amp;lt;Book&amp;gt; Books { get; set; }    public DbSet&amp;lt;Author&amp;gt; Authors { get; set; }      }


A questo punto aggiungiamo un WCF Data Service al progetto Web:

 



 

Rinominiamolo in LibraryService.svc. Per utilizzare la versione CTP 2 è necessario eliminare i riferimenti alle librerie System.Data.Services e System.Data.Services.Client ed aggiungere i riferimenti alle librerie Microsoft.Data.Services e Microsoft.Data.Services.Client presenti nella directory Bin presente nel percorso di installazione della versione di WCF Data Service appena installata. Dovremmo ottenere qualcosa del genere:



Oltre alle altre References. Modifichiamo il codice della classe LibraryService in questo modo:


  public class LibraryService : DataService&amp;lt;LibraryContext&amp;gt;{    public static void InitializeService(DataServiceConfiguration config)    {        config.SetEntitySetAccessRule("Books", EntitySetRights.All );        config.SetEntitySetAccessRule("Authors", EntitySetRights.All);        config.SetServiceOperationAccessRule("FindBooksByTitle", ServiceOperationRights.AllRead);        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;    }    [WebGet]    public IQueryable&amp;lt;Book&amp;gt; FindBooksByTitle(string title)    {        return (from b in CurrentDataSource.Books where b.Title.Contains(title) select b);    }}


Dove utilizziamo direttamente la nostra classe LibraryContext senza strane alchimie (override). Tramite l’InitializeService configuriamo il servizio per l’accesso alle entità “Books” ed “Authors”, configuriamo la versione del protocollo da utilizzare (DataServiceProtocolVersion.V3) e l’accesso a FindBooksByTitle  che permette di trovare tutti i libri che contengono un determinato titolo. Se utilizziamo del codice simile al seguente per creare e popolare la base dati sottostante: 


  Book book1 = new Book(){    Title = "Programming .Net 4 in C#",    Summary = "Progamming .Net Framework 4 Book (C#)"};Book book2 = new Book(){    Title = "Programming .Net 4 in VB.NET",    Summary = "Progamming .Net Framework 4 Book (VB.NET)"};Author author = new Author(){     Name="Tizio Caio"};author.Books = new List&amp;lt;Book&amp;gt;();author.Books.Add(book1);author.Books.Add(book2);cnt.Books.Add(book1);cnt.Authors.Add(author);cnt.SaveChanges();

Possiamo avviare il sito tramite il Server Web locale ed utilizzare direttamente il browser per interagire con il servizio. Ad esempio possiamo recuperare la lista dei “Book” presenti digitando: http://localhost:5104/LibraryService.svc/Books o visualizzare i metadata esposti digitando http://localhost:5104/LibraryService.svc/$metadata. Passiamo a qualcosa di più concreto aggiungendo un’applicazione console alla nostra soluzione, creando un riferimento al servizio tramite la voce di menu “Add Service Reference”. Visual Studio crea per noi tutte le classi proxy necessarie ed un file Service.edmx con la definizione del modello. Testiamo il tutto aggiungendo del codice nel Main della classe Program:


  LibraryServiceReference.LibraryContext ctx = new LibraryServiceReference.LibraryContext(new Uri("http://localhost:5104/LibraryService.svc/")); #region Add Book and Author Book book = new Book { Title = "Programming C# 4", Summary = "aaa" }; Author author = new Author { Name = "Tizio Caio" }; author.Books.Add(book); ctx.AddToBooks(book); ctx.AddToAuthors(author); ctx.AddLink(author, "Books", book); ctx.SaveChanges(); Console.WriteLine(ctx.Books.Count()); #endregion #region Update Book Title book.Title = "Programming .NET 4 in C#"; ctx.UpdateObject(book); ctx.SaveChanges(); Book storedBook = ctx.Books.Where(p =&amp;gt; p.Id == book.Id).Select(p =&amp;gt; p).FirstOrDefault(); Console.WriteLine("Book Title={0}", book.Title); #endregion #region Delete Book-Author link Author storedAuthor = (from a in ctx.Authors.Expand("Books")                        where a.Name.Equals("Tizio Caio")                        select a)                        .FirstOrDefault(); Console.WriteLine("Author={0}, Book Title={1}",storedAuthor.Name , storedAuthor.Books[0].Title); ////Delete Link. Set null value in author_id column (Books Table). ctx.DeleteLink(storedAuthor, "Books", storedAuthor.Books[0]); ctx.SaveChanges(); #endregion

Il codice interagisce con un’istanza della LibraryContext sottostante per Aggiungere\Modificare\Eliminare i dati presenti nella base dati. Se volessimo interagire tramite HTTPWebRequest, potremmo scrivere del codice simile al seguente:


  #region HttpWebRequest////Get all BooksHttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://localhost:5104/LibraryService.svc/Books"));webRequest.Method = "GET";webRequest.Accept = "application/json";HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();System.IO.StreamReader streamReader = new System.IO.StreamReader(webResponse.GetResponseStream());string jSONResponse = streamReader.ReadToEnd();Console.WriteLine(jSONResponse);////Find Books by title.webRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://localhost:5104/LibraryService.svc/FindBooksByTitle?title='Programming'"));webRequest.Method = "GET";webRequest.Accept = "application/json";webResponse = (HttpWebResponse)webRequest.GetResponse();streamReader = new System.IO.StreamReader(webResponse.GetResponseStream());jSONResponse = streamReader.ReadToEnd();Console.WriteLine(jSONResponse);#endregion#region Delete all objects////Delete Objects.ctx.DeleteObject(author);ctx.DeleteObject(book);ctx.SaveChanges();#endregion
In entrambi i casi i dati vengono restituiti in formato JSON, quindi facilmente parsabili. Possiamo verificare come le nostre query LINQ siano tradotte in chiamate HTTP gestendo l’evento SendingRequest del servizio:


  static void ctx_SendingRequest(object sender, System.Data.Services.Client.SendingRequestEventArgs e){    Console.WriteLine(e.Request.RequestUri.ToString());}
&lt;img src="http://blogs.ugidotnet.org/PietroLibroBlog/aggbug/100037.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/05/15/wcf-data-service-ctp2-e-ef-4.1.aspx</guid>
            <pubDate>Sun, 15 May 2011 20:55:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/PietroLibroBlog/archive/2011/05/15/wcf-data-service-ctp2-e-ef-4.1.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/PietroLibroBlog/comments/commentRss/100037.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/PietroLibroBlog/services/trackbacks/100037.aspx</trackback:ping>
        </item>
    </channel>
</rss>