<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>Entity Framework 5</title>
        <link>http://blogs.ugidotnet.org/pietrolibroblog/category/Entity Framework 5.aspx</link>
        <description>Entity Framework 5</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>EF6 (beta1) - Code First Stored Procedures Mapping</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2013/06/26/ef6-beta1-code-first-stored-procedures-mapping.aspx</link>
            <description>Una delle features che sicuramente in molti aspettavano con la nuova release di EF è la possibilità di eseguire il mapping delle entità tramite Stored Procedures. Con la versione 6 di Entity Framework (attualmente in beta 1), abbiamo finalmente questa possibilità, e l'utilizzo è veramente immediato.  Supponiamo di avere un Domain Model simile a quello mostrato nella figura seguente:     Dove abbiamo un insieme di oggetti ereditati, ed una navigation property che collega l'oggeto Car ad una collezione di oggetti Optional.   Aggiungiamo il riferimento ad EF6 utilizzando il gestore di "NuGet Packages" selezionando tra le varie opzioni "Include Prerelease" e poi selezioniamo il package "Entity Framework":     Eseguiamo la configurazione delle classi che compongono il nostro Domain tramite Code First Fluent Api ed aggiungiamo il codice seguente:   modelBuilder.Entity&amp;lt;Domain.Car&amp;gt;().MapToStoredProcedures();
 modelBuilder.Entity&amp;lt;Domain.Optional&amp;gt;().MapToStoredProcedures();

 

Il quale "informa" il run-time di Entity Framework che per le entità "Car" ed "Optional" le operazioni di Insert\Delete\Update verranno utilizzate delle Stored Procedures (che rispondono alle convenzioni richieste da EF). 

A questo punto entra in scena EF Migrations ed il "fantastico" comando "Add-Migration", che produce tutto il codice, e non solo, necessario ad aggiornare il database:

 public override void Up()
        {
            CreateStoredProcedure(
                "DomusDotNet.Car_Insert",
                p =&amp;gt; new
                    {
                        Brand = p.String(maxLength: 128),
                        Model = p.String(maxLength: 128),
                        EngineSize = p.String(maxLength: 128),
                        HP = p.Int(),
                        DailyRent = p.Single(),
                        FreeDailyKm = p.Int(),
                        Note = p.String(maxLength: 128),
                    },
                body:
                    @"INSERT [DomusDotNet].[Vehicles]([Brand], [Model], [EngineSize], [HP], [DailyRent], [FreeDailyKm], [Note])
                      VALUES (@Brand, @Model, @EngineSize, @HP, @DailyRent, @FreeDailyKm, @Note)
                      
                      DECLARE @Id int
                      SELECT @Id = [Id]
                      FROM [DomusDotNet].[Vehicles]
                      WHERE @@ROWCOUNT &amp;gt; 0 and [Id] = scope_identity()
                      
                      INSERT [DomusDotNet].[Cars]([Id])
                      VALUES (@Id)
                      
                      SELECT t0.[Id]
                      FROM [DomusDotNet].[Vehicles] as t0
                      WHERE @@ROWCOUNT &amp;gt; 0 and t0.[Id] = @Id"
            );
            
           ...


Unico neo, se utilizzate uno schema diverso da "dbo" (anche se avete specificato tramite la nuova API HasDefaultSchema("...") lo schema corretto) bisogna modificare manualmente il nome delle Stored Procedures, altrimenti a run-time verrà generata un'eccezione.

Scriviamo del codice di test tipo:

int rowsAffected = 0;

Domain.Car fordFocus = new Domain.Car()
{
    Brand = "FORD",
    DailyRent = 45.0f,
    EngineSize = "1600",
    FreeDailyKm = 100,
    HP = 115,
    Model = "Focus",
    Note = "With Radio and Power Steering."
};

fordFocus.Optionals.Add(new Domain.Accesory() { Description = "Radio Sony", Removable = true, Price = 10 });
fordFocus.Optionals.Add(new Domain.Accesory() { Description = "Power Steering", Removable = false, Price = 0 });

using (Data.CarRentalDB db = new Data.CarRentalDB())
{
    db.Cars.Add(fordFocus);
    rowsAffected = db.SaveChanges();
}

Utilizzando il nostro amico "Sql Profiler" vediamo come le operazioni di accesso alla tabella per Insert\Update\Delete utilizzano le Stored Procedures generate in precedenza:

 

Di questo ed altro parleremo in dettaglio durante l'evento EF@Work organizzato da DomusDotNet :-)&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/101596.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2013/06/26/ef6-beta1-code-first-stored-procedures-mapping.aspx</guid>
            <pubDate>Wed, 26 Jun 2013 10:30:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2013/06/26/ef6-beta1-code-first-stored-procedures-mapping.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/101596.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/101596.aspx</trackback:ping>
        </item>
        <item>
            <title>Web API: Circular Object References</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/08/22/web-api-circular-object-references.aspx</link>
            <description>Quando utilizziamo le Web API, per leggere e scrivere oggetti nel corpo di un messaggio Http utilizziamo delle classi particolari, le media-type formatters. "Gratis" Web API fornisce media-type formatters per JSON e XML, utilizzate secondo della richiesta da parte dei client (“Accept”). Se JSON e XML non sono i "formati" di cui abbiamo bisogno possiamo sempre creare la nostra classe derivata da MediaTypeFormatter o BufferedMediaTypeFormatter, rispettivamente per scenari asincroni o sincroni, ma non sono l’argomento di questo post promemoria.  Quando abbiamo a che fare con grafi di oggetti complessi, possono crearsi situazioni in cui abbiamo riferimenti circolari tra oggetti. Ad esempio in uno scenario di questo tipo:    Dove abbiamo due classi, Book ed Author , referenziate tramite collection (praticamente un’associazione molti-a-molti) l’una con l’altra.   Se abbiamo una Web API di questo tipo :  private BookshelfDb _db = new BookshelfDb();
public IEnumerable&amp;lt;Book&amp;gt; GetBooks()
{
    return _db.Books.Include(b =&amp;gt; b.Authors).AsEnumerable();
}
...


ed una configurazione standard delle Web API, ad eccezione dell’indentatura:

JsonMediaTypeFormatter json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.Indent = true;


In presenza di dati, invocando GetBooks() (ad esempio tramite browser), otterremo un’eccezione di questo tipo:

{ 
  "Message": "An error has occurred.", 
  "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.", 
  "ExceptionType": "System.InvalidOperationException", 
  "StackTrace": null, 
  "InnerException": { 
    "Message": "An error has occurred.", 
    "ExceptionMessage": "Self referencing loop detected with type 'BookshelfWebApi.Models.Book'. Path '[0].Authors[0].Books'.", 
    "ExceptionType": "Newtonsoft.Json.JsonSerializationException", 
    "StackTrace": "   …
}


La soluzione al problema è abbastanza semplice  in quanto è sufficiente aggiungere la riga:

json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;


Il caso Xml, non è immediato come nel caso JSON, in quanto è necessario decorare le classi con l’attributo DataContract impostando la proprietà IsReference a true. In questo caso però è necessario decorare anche le proprietà con l’attributo DataMember:

[DataContract(IsReference = true)]
public class Book
{
    public Book()
    {
        this.Authors = new List&amp;lt;Author&amp;gt;();
    }
    [DataMember()]
    public int Id { get; set; }
    [DataMember()]
    public int Paperback { get; set; }
    [DataMember()]
    public string Title { get; set; }
    [DataMember()]
    public string ISBN_10 { get; set; }
    [DataMember()]
    public string ISBN_13 { get; set; }
    [DataMember()]
    public string Language { get; set; }
    [DataMember()]
    public string Publisher { get; set; }
    [DataMember()]
    public ICollection&amp;lt;Author&amp;gt; Authors { get; set; }
}


Se non si vuole “sporcare” le classi “farcendole” di attributi possiamo optare per un DataContractSerializer. Le Web API possono essere configurate modificando il codice presente nella classe WebApiConfig.cs:



Quanto detto è sicuramente famigliare per chi espone entità collegate tramite Http, ad esempio utilizzando WCF.&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/101168.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/08/22/web-api-circular-object-references.aspx</guid>
            <pubDate>Wed, 22 Aug 2012 11:17:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/08/22/web-api-circular-object-references.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/101168.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/101168.aspx</trackback:ping>
        </item>
        <item>
            <title>EF5 Released</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/08/16/ef5-released.aspx</link>
            <description>Con l’arrivo in RTM di Windows 8 e Visual Studio 2012 è stata rilasciata la nuova versione di Entity Framework (scaricabile ovviamente tramite NuGet). Le novità presenti sono diverse, quella più “gettonata” è sicuramente il supporto agli “Enum”. Diverse novità coinvolgono anche il Designer di EF per Visual Studio 2012, come il supporto a diagrammi multipli per lo stesso modello (una delle funzionalità che più apprezzo).   Per tutti i dettagli del caso, per la compatibilità delle funzioni utilizzabili secondo del targeting del .NET Framework, lista dei bug corretti ed altro, è possibile iniziare da qui. &lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/101156.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/08/16/ef5-released.aspx</guid>
            <pubDate>Thu, 16 Aug 2012 08:54:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/08/16/ef5-released.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/101156.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/101156.aspx</trackback:ping>
        </item>
        <item>
            <title>EF5 RC</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/05/16/ef5-rc.aspx</link>
            <description>Rilasciata la versione Release Candidate di Entity Framework 5. Il download al solito è disponibile tramite NuGet sia per .Net 4 (in questo caso alcune features non sono supportate, come Enum e Spatial Data) e .Net 4.5.
Dettagli e nuovi  Walkthrough disponibili sul blog del team di ADO.NET.&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/101003.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/05/16/ef5-rc.aspx</guid>
            <pubDate>Wed, 16 May 2012 10:58:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/05/16/ef5-rc.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/101003.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/101003.aspx</trackback:ping>
        </item>
    </channel>
</rss>