<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</title>
        <link>http://blogs.ugidotnet.org/dsantarelli/category/Entity Framework.aspx</link>
        <description>Entity Framework</description>
        <language>it-IT</language>
        <copyright>Dario Santarelli</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>[Entity Framework v4] Creazione dei tipi proxy</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2011/11/27/entity-framework-v4-creazione-dei-tipi-proxy.aspx</link>
            <description>L’approccio POCO di Entity Framework v4 permette di applicare la persistence-ignorance anche su oggetti custom attraverso la creazione a runtime (via Reflection.Emit) di proxy dinamici che li derivano in modo da permettere all’EF di implementarci sopra i suoi meccanismi di change tracking e lazy loading. In particolare, il change tracking è una feature che un oggetto proxy potrebbe continuare a mantenere anche quando attraversa tier diversi, il che ovviamente sposta l’attenzione verso problematiche legate alla serializzazione di oggetti il cui tipo effettivo non è disponibile a compile time. 
Ad esempio, se volessimo serializzare e deserializzare su tier diversi un nostro oggetto Customer, il processo che si troverebbe a deserializzare il corrispondente tipo proxy autogenerato dall’EF dovrebbe essere in grado di riconoscere un oggetto di tipo...
System.Data.Entity.DynamicProxies.Customer_1941BFC82D29CB600101CF80564EA2CCAE83E1ACF5EF4B32E482FBDF13337DC9 
definito nell’assembly (fittizio)
EntityFrameworkDynamicProxies-&amp;lt;NostroAssembly&amp;gt;, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
che ovviamente non è un “known type” nel suo AppDomain.   

Ora, se utilizzassimo WCF come infrastruttura di comunicazione, non avremmo alcuna feature “gratis” per serializzare e deserializzare direttamente i tipi proxy di EF poiché il DataContractSerializer è in grado di gestire solo “known types” e purtroppo i proxy dinamici non lo sono. Quindi, le principali opzioni per aggirare il problema sono:

    Disabiltare la creazione dei proxy tramite la proprietà ProxyCreationEnabled (es. context.ContextOptions.ProxyCreationEnabled = false;) in modo da lavorare direttamente sui known types, ma perdendo ovviamente il change tracking automatico di EF.
    Usare la classe ProxyDataContractResolver per mappare i tipi proxy direttamente sui nostri tipi custom (esempio) che però a quel punto non supporterebbero più né il change tracking né tantomeno il lazy loading di EF. Soluzione sicuramente migliore per continuare a mantenere il change tracking su più tier è far riferimento a “self-tracking entities” ovvero ad oggetti che non hanno nessuna dipendenza con EF e definiscono internamente la loro logica di change tracking (ad esempio implementando l’interfaccia INotifyPropertyChanged).

Senza WCF c’è sempre la serializzazione “old-fashioned”. Ad esempio quella binaria. Affinché i tipi proxy siano resi disponibili alla deserializzazione binaria, EF ci espone un metodo CreateProxyTypes sull’oggetto ObjectContext per assicurare che i tipi proxy relativi ad un dato MetadataWorkspace siano deserializzabili all’interno di un AppDomain diverso da quello che invece li serializza. Occorre tenere a mente che la deserializzazione dei proxy ricostruisce degli oggetti che ovviamente non mantengono il loro comportamento originale (quindi niente change tracking). 
Il seguente metodo, invocato ad esempio allo startup di una applicazione, è in grado di scatenare nell'AppDomain corrente la creazione di tutti i tipi proxy corrispondenti alle entity definite negli EDM (Entity Data Model) deployati come risorse all’interno di una lista di assembly, in modo che il BinaryFormatter sia poi in grado di trattare tali tipi come “known types”.
 
public static void CreateProxyTypes(Assembly[] assembliesToConsider) {
   var metadataWorkspace = new MetadataWorkspace(new string[] { "res://*/" }, assembliesToConsider);        using (var entityConnection = new EntityConnection(metadataWorkspace, new SqlConnection()))        {              using (var context = new ObjectContext(entityConnection))              {                     foreach (var assembly in assembliesToConsider)                     {                           context.CreateProxyTypes(assembly.GetTypes());                     }                                  }        } }
 
Da notare come la classe EntityConnection richieda nel costruttore una connessione ad un data source che ai nostri fini però non è importante specificare. Per questo viene passata una SqlConnection “vuota”. Ciò che conta è referenziare gli EDM deployati come risorse all’interno degli assembly specificati. CreateProxyTypes è un metodo intelligente in quanto è in grado di ignorare tutti i tipi che non sono rappresentati negli EDM, quindi possiamo tranquillamente passargli come argomento tutti i tipi definiti all’interno di un assembly: esso internamente sarà in grado di controllare la sua cache di tipi e di trasformare in known types soltanto i tipi proxy di EF che ancora non sono stati creati. Per avere controprova dei tipi proxy correntemente registrati nel nostro AppDomain, basta chiamare il metodo statico ObjectContext.GetKnownProxyTypes(). 
Technorati tags: EntityFramework,Serialization,DynamicProxy&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/100561.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2011/11/27/entity-framework-v4-creazione-dei-tipi-proxy.aspx</guid>
            <pubDate>Sun, 27 Nov 2011 20:55:21 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2011/11/27/entity-framework-v4-creazione-dei-tipi-proxy.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/100561.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/100561.aspx</trackback:ping>
        </item>
        <item>
            <title>[Entity Framework] Gestione runtime dei metadati</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/30/entity-framework-gestione-runtime-dei-metadati.aspx</link>
            <description>Il comportamento di default del wizard dell’EF accorpa i metadati del modello come risorse del nostro assembly e inserisce una stringa di connessione nell’ app.config o nel web.config in modo da referenziare a runtime tali risorse:        &amp;lt;connectionStrings&amp;gt;      &amp;lt;add name="NorthwindEntities"             connectionString="metadata=res://*/NorthwindModel.csdl|res://*/NorthwindModel.ssdl|res://*/NorthwindModel.msl;..."            providerName="System.Data.EntityClient" /&amp;gt;        &amp;lt;/connectionStrings&amp;gt;  Tuttavia, “embeddare” i metadati del nostro modello come risorsa dell’assembly può costituire un limite: infatti sorgerebbero dei problemi qualora volessimo     esporre i metadati alla modifica di agenti esterni     referenziare tramite connection string dei metadati definiti altrove sul file system     caricare i metadati on-demand magari leggendoli da stream di rete   Infatti, esistono dei casi in cui può essere utile distinguere tra metadati di test e metadati di produzione o comunque prevedere delle politiche che possano richiedere storage model (SSDL) e mapping model (MSL) diversi, pur mantenendo l’integrità del modello concettuale (CSDL) utilizzato dallo sviluppatore.  Una prassi molto comune è impostare l’opzione 'Metadata Artifact Processing' del designer a 'Copy to Output Directory'.               In questo modo nella bin del nostro progetto troviamo i metadati SSDL, MSL e CSDL separati fisicamente dalla .dll di output.     Quindi abbiamo già raggiunto l’obiettivo di poter modificare i metadati (solitamente SSDL e MSL) senza dover ricompilare la nostra applicazione. A questo punto possiamo scegliere di modificare la nostra connection string in modo che punti al corretto insieme di file:         string connectionString = @"metadata=.\NorthwindModel.csdl|.\NorthwindModel.ssdl|.\NorthwindModel.msl;                                     provider=System.Data.SqlClient; provider connection string=""..."" ";           using (NorthwindContext context = new NorthwindContext(connectionString)) { ... }     Uno step ulteriore che si può prevedere è il caricamento dinamico di metadati non soltanto da una locazione fisica su file system, ma anche da un generico stream (es. da un web server via HTTP). A riguardo, il seguente esempio mostra come caricare dinamicamente CSDL, SSDL e MSL in modo da creare un oggetto di tipo EntityConnection da passare al nostro ObjectContext:        // Get CSDL/SSDL/MSL from a generic stream ...      string csdl = "&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&amp;lt;Schema...&amp;lt;/Schema&amp;gt;";      string ssdl = "&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&amp;lt;Schema...&amp;lt;/Schema&amp;gt;";      string msl = "&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&amp;lt;Mapping...&amp;lt;/Mapping&amp;gt;";           XmlTextReader csdlXmlReader = new XmlTextReader(new StringReader(csdl));      XmlTextReader ssdlXmlReader = new XmlTextReader(new StringReader(ssdl));      XmlTextReader mslXmlReader = new XmlTextReader(new StringReader(msl));      EdmItemCollection edmItemCollection = new EdmItemCollection(new[] { csdlXmlReader });      StoreItemCollection storeItemCollection = new StoreItemCollection(new[] { ssdlXmlReader });      StorageMappingItemCollection storageMappingItemCollection = new StorageMappingItemCollection(edmItemCollection, storeItemCollection, new[] { mslXmlReader });                      // Create the metadata workspace for the EntityConnection ...     MetadataWorkspace metadataWorkspace = new MetadataWorkspace();      metadataWorkspace.RegisterItemCollection(edmItemCollection);     metadataWorkspace.RegisterItemCollection(storeItemCollection);     metadataWorkspace.RegisterItemCollection(storageMappingItemCollection);           string sqlConnectionString = @"Data Source=.\SQLSRV08;Initial Catalog=Northwind;User ID=XXX;Password=XXX;";  EntityConnection entityConnection = new EntityConnection(metadataWorkspace,new SqlConnection(sqlConnectionString));            using (NorthwindContext context = new NorthwindContext(entityConnection)) { ... }            Technorati Tag: Entity Framework,EF,metadati&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/97926.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/30/entity-framework-gestione-runtime-dei-metadati.aspx</guid>
            <pubDate>Sat, 30 Jan 2010 17:49:43 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/30/entity-framework-gestione-runtime-dei-metadati.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/97926.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/97926.aspx</trackback:ping>
        </item>
    </channel>
</rss>