{"id":35,"date":"2008-12-14T15:15:27","date_gmt":"2008-12-14T19:15:27","guid":{"rendered":"http:\/\/blogs.law.harvard.edu\/brandonhaynes\/?p=35"},"modified":"2009-02-19T15:24:54","modified_gmt":"2009-02-19T19:24:54","slug":"entity-framework-to-idatareader-adapter","status":"publish","type":"post","link":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/2008\/12\/14\/entity-framework-to-idatareader-adapter\/","title":{"rendered":"First Look: An Entity Framework (LINQ to Entity) to IDataReader Adapter"},"content":{"rendered":"<p>Microsoft&#8217;s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb386992.aspx\">Entity Framework<\/a> (EF) introduces a new data design paradigm within .NET. This framework, however, can be difficult to implement in projects that internally rely heavily on the exchange of <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.data.idatareader.aspx\">IDataReader<\/a>-implementing objects between layers (or within interface contracts). This is a shortcoming that is not easily overcome, especially without a standardized method with which to convert EF entities into an object implementing this interface. In many ways, migration of these projects to the Entity Framework is an all-or-nothing proposition.\u00a0 This is a shortcoming that begs for remediation.\u00a0<\/p>\n<p><!--more-->Indeed, it would be advantageous to provide adaptation for entities within an EF\/LINQ to Entity (L2E) model that was usable in such a legacy system. New code could directly utilize entity classes, while legacy interfaces could function as before. Such a system could be incrementally converted to a full EF implementation. This incremental approach has many practical advantages.<br \/>\n<a href=\"http:\/\/blogs.law.harvard.edu\/brandonhaynes\/files\/2008\/12\/idatareaderadaptermodel.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-full wp-image-36\" style=\"float: right\" src=\"http:\/\/blogs.law.harvard.edu\/brandonhaynes\/files\/2008\/12\/idatareaderadaptermodel.png\" alt=\"Layering of the IDataReader adapter model on top of the Entity Framework stack\" width=\"276\" height=\"716\" \/><\/a><br \/>\nHerein (and over the next few related entries)\u00a0is described an approach that resolves this shortcoming.\u00a0 In its current form, it exists as a new layer at the top of the EF stack, as depicted in Figure 1 (right).\u00a0 This layer is responsible for adapting EF entities to objects that implement the IDataReader\u00b9 interface.<\/p>\n<p>The resultant adapted IDataReaders may be used in any way, include across layers, so long as the underlying entities expose those properties expected by a consumer (including exposure through direct entity relationship).<\/p>\n<p>Accordingly, the primary goals for this project include the following:<\/p>\n<ul>\n<li>Provide a per-entity adapter for each entity in a model, where each adapter implements the IDataReader\u00a0and IDataRecord interfaces for use in legacy systems.<\/li>\n<li>The resultant IDataReaders should be internally strongly-typed and performant (and thereby not use reflection\u00b2).<\/li>\n<li>Model adaptation should be straightforward and easy to update as the model itself changes.<\/li>\n<li>Adapters should expose all entity properties, including &#8220;flattened&#8221; properties established through entity relationships (as exposed through conceptual model NavigationProperties).<\/li>\n<\/ul>\n<p>These objectives are best accomplished through code generation.\u00a0 This has the attractive characteristics of: compile-time validation, multiple-language targeting, model synchronization on a per-compile basis, performance gains, and strongly-typed code (an advantage given that an entity contains an arbitrary set of unknown properties).<\/p>\n<p>Once adapted, we may\u00a0construct a function that converts an entity (or set of entities) to an IDataReader-implementing construct, with code\u00a0of the following general form:\u00a0<\/p>\n<div style=\"border: dashed 1px black;padding: 0.5em;margin-left: 1em\"><code>public IDataReader GetEntities()<br \/>\n{<br \/>\nusing (var context = new EntityContext())<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return new DataReaders.EntityDataReader(context.Entities);<br \/>\n}<\/code><\/div>\n<p>Over the next few entries, we (i) describe use of the IDataReaderAdapter generation tool, (ii) investigate the generated IDataReader-implementing adapters in more detail, (iii) generate and discuss performance metrics, and (iv) implement a case-study utilization of adapter generation (demonstrating a database-agnostic <a href=\"http:\/\/www.dotnetnuke.com\">DotNetNuke<\/a> hybrid data provider).<\/p>\n<p>This project is available for public evaluation and consumption <a title=\"Entity Framework IDataReader Adapter\" href=\"http:\/\/www.codeplex.com\/L2EDataReaderAdapter\">here<\/a>\u00b3.\u00a0 It is distributed with a liberal source license for use in production environments.\u00a0<\/p>\n<p>For any that find this approach useful, or for those with additional questions, comments, or constructive criticism, I ask that you provide feedback here (or at the CodePlex site).\u00a0 Your assessments and observations are an important part of any continued development.<\/p>\n<p>B<\/p>\n<hr \/>\n<p>\u00b9\u00a0Though this entry often refers to the IDataReader interface, the approach described herein may also be used to generate IDataRecord-compatible objects.\u00a0 This latter contract may be substituted for the former in most every reference herein.<\/p>\n<p>\u00a0<\/p>\n<p>\u00b2\u00a0For types not known at compile-time, we include a reflection-enabled adapter.\u00a0 Note that such an adapter may be used to adapt <em>any<\/em> object, including non-EF entity objects.\u00a0 This additional flexibility is achieved at the expense of overall performance.<\/p>\n<p>\u00b3 Project is expected to go live on or about December 15th, 2008.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft&#8217;s Entity Framework (EF) introduces a new data design paradigm within .NET. This framework, however, can be difficult to implement in projects that internally rely heavily on the exchange of IDataReader-implementing objects between layers (or within interface contracts). This is a shortcoming that is not easily overcome, especially without a standardized method with which to [&hellip;]<\/p>\n","protected":false},"author":1933,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3901,142],"tags":[3900,3279,3899,19469],"class_list":["post-35","post","type-post","status-publish","format-standard","hentry","category-entity-framework-ef","category-technology","tag-entity-framework","tag-linq","tag-linq-to-entities","tag-technology"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/posts\/35","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/users\/1933"}],"replies":[{"embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/comments?post=35"}],"version-history":[{"count":0,"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/posts\/35\/revisions"}],"wp:attachment":[{"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/media?parent=35"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/categories?post=35"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/archive.blogs.harvard.edu\/brandonhaynes\/wp-json\/wp\/v2\/tags?post=35"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}