image It was an amazing TechEd NA 2010, and I admit that it took me a few days to recover.  Between the heat and humidity, great times with friends, and good food, I managed to spend a bit of time at the conference.

I had the pleasure of co-presenting with Jerome Schulist, a solutions architect at the Tribune Company.  Jerome is one of the architects that engineered the solution that has allowed the Tribune Company to store and process terabytes of data on the Windows Azure platform.  This solution involves a number of really interesting scenarios, including:

  • Parallelized upload of terabytes of digital content into Windows Azure blob storage using .NET Framework 4.0
  • Best practices for uploading a massive amount of content
  • Scaling strategy for Windows Azure blob storage through multiple storage accounts and a “round robin” pattern
  • Content reprocessing with Windows Azure worker roles
  • Automatic scale-out and scale-back of worker roles through queue lengths

For detailed information on this solution, you can take a look at the Tribune Company’s Windows Azure case study or you can watch our TechEd NA 2010 presentation here:

Get Microsoft Silverlight

As promised in the session, you can find the final code built during the session below.  Just remember to update the config files with your own credentials.

Windows Azure One of the advantages to the approach our teams building the Windows Azure Platform have taken is flexibility.  Recently, when I spoke at the Day of Cloud presentation, I recall Don Schwarz from Google making these two points (you can see video of his talk here):

  • You can’t spin up your own threads in Google App Engine.
  • You build your applications according to how Google thinks your apps should be built (the argument being that Google knows how to run highly available services at scale, which I think is a fair statement).

Now to be fair, there are good reasons for this – the Google App Engine has a number of very good use cases (Don Schwarz demonstrated one of them when showing the audience a multiplayer game running on Google App Engine).

Note: I’d like state for the record that I mean no criticism of other cloud vendors (i.e. Amazon, Google, and SalesForce).  I think each of them have a place in the market, and exhibit various strengths.  That said, I do believe that the Windows Azure Platform stands out as the only real platform that can bridge the chasm between cloud services and on-premises software. (Note to self: back this statement up in a future blog post.)

I would argue, however, that most enterprise developers require a little more flexibility when building out enterprise class applications.  The Windows Azure Platform provides this flexibility (I mean, come on – sometimes you just want to execute some native code!).

I decided to test how far I could take this flexibility in Windows Azure.

I am a big fan of Worker Roles in Windows Azure.  I really like the idea of having an asynchronous, “headless” service that’s working for me in the background.  I wanted to see if I could spin up an equivalent to a Worker Role in a Web Role, so that in addition to having my Web application running in a Web Role I could also get a service running in the background.

Why would I want to do this?  Well, here are a few of reasons:

  • Asynchronous logging service running in every Azure instance (whether a web or worker role); this service might take information from the event log and write it to an Azure table.
  • Clean-up operations (i.e. temporary scratch writes, etc.)
  • Opening and managing socket connections to the service bus (this is my favorite scenario).

The list could go on.  Hopefully you get the point.

So, how would you do this?  Again, given the flexibility of the platform, there are many ways you can do this.  Below you’ll find one simple way.

1. Create a new cloud services project, and add a web role.

2. Create a new class and inherit from Microsoft.ServiceHosting.ServiceRuntime.RoleEntryPoint.  You’ll have to override the Start and RoleStatus methods.

using Microsoft.ServiceHosting.ServiceRuntime;
using System.Threading;

namespace Web
{
    public class MyWebWorkerRole : RoleEntryPoint
    {
        public override void Start()
        {
            while (true)
            {
                RoleManager.WriteToLog("Information", "The worker role is running.");

                Thread.Sleep(5000);
            }
        }

        public override RoleStatus GetHealthStatus()
        {
            return RoleStatus.Healthy;
        }
    }
}

3. Create a Global.asax page.

4. Create a method where you initialize and start and initialize your class that inherits from RoleEntryPoint.

private void StartWorkerRole()
{
    MyWebWorkerRole myWebWorkerRole = new MyWebWorkerRole();
    myWebWorkerRole.Initialize();
    myWebWorkerRole.Start();
}

5. Create local threading variables that you will use to run your method.

public class Global : System.Web.HttpApplication
{
    System.Threading.ThreadStart ts;
    System.Threading.Thread t;

    ...

5. Update the Application_BeginRequest method to invoke your method on a new thread.  Be sure and check to see if the thread is already running, otherwise it will get started multiple times.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (t == null)
    {
        ts = new System.Threading.ThreadStart(StartWorkerRole);
        t = new System.Threading.Thread(ts);
        t.Start();
    }
}

And that should do it.  Now you have a class that will run asynchronously in all your Web Role instances.  And since it inherits from the RoleEntryPoint, you can leverage this technique for both your Web and Worker Role instances.  I’d recommend placing this class in a separate class library and adding a reference to it from your various projects.

Note: It is highly probable that there will be some changes to the APIs and assemblies come PDC.  While these concepts will stay valid, the underlying code will probably change.  If this happens, I’ll be sure and provide an update.

I hope this helps!

Warning: Please note that this post was written prior to the launch of Windows Identity Foundation. Most of the steps outlined below are no longer accurate nor necessary.

One of the critical elements a company needs to consider when moving to the cloud is how they will leverage their existing identity stores.  Most companies have made significant investments in various identity solutions (i.e. providing for SSO, identity consolidation, federating with partners, etc.) and it’s imperative to ensure that applications and services in the cloud can take advantage of these resources.

Background

The practice of enabling the portability of identity information across otherwise autonomous security domains, called identity federation, is no longer a luxury – it’s a necessity.  The inability to allow users to access resources in different datacenters, with various trading partners, or on the Web, can quickly cripple a companies productivity (not to mention user satisfaction).  Historically, providing for the needs of Web-based single sign on (SSO) and cross-domain resource access has been very difficult to accomplish.  It may have required the replication of identity stores in a host of one-off scenario, or even (gasp!) compromising security best practices in order to satisfy a business need.

More recently, various kinds of identity architecture have made identity federation much easier.  Practices like claims-based authentication, standards like WS-Federation, and so forth allow companies to establish trust domains between different organization and parties much easier.  See the following illustration from InfoQ:

Claims-based identity with tokens

In this picture, the application implicitly trusts tokens that come from the issuer.  Consequently, rather than having to authenticate the users identity, the application can delegate that responsibility to the issuer, and instead focus on parsing the information received in the token.  These tokens contain claims, which are nothing more than bits of information about a person, such as a name, email address, membership in a particular role, and so on.  If your application trusts the issuer of the claim, you can leverage the information without having to query the identity store directly.

While it is possible to build a customer claims issuer (or more appropriately called a security token service), there are a host of solutions available today that make this quite easy.  Microsoft’s Active Directory Federation Services (ADFS) is a great example, and work implicitly with identities stored in active directory.  ADFS allows for federated identity by implementing claims-based authentication and establishing trust between different organizations and parties.

ADFS v2 (which was previously codenamed "Geneva" Server") expands this capability by bringing claims-based identity federation to cloud-based applications that live in on the web, in the enterprise, or across an organization.  The "Geneva" Beta 2 datasheet provides the following description that I think is a great summation of ADFS v2:

“Geneva” is Microsoft’s next generation identity and access management platform built on Active Directory® directory services. “Geneva” provides claims-based access and single sign-on for on-premises and cloud-based applications in the enterprise, across organizations, and on the Web.

“Geneva” leverages claims which describe identity attributes and can be used to drive application and other system behaviors with an open architecture that implements the industry’s shared Identity Metasystem vision.

A few things I’d like to point out about ADFS v2 that make it very powerful:

  • Open standards.  ADFS v2 is based on SAML 2.0, so it can interoperate with products from all kinds of vendors and platforms.
  • Automation.  ADFS v2 handles the federation of identities by setting up the trust relationships.
  • Developer productivity.  Since developers interact with trusted claims, they don’t have to spend time worry about the particulars of the identity provider.

In this post, I want to highlight how you can use ADFS v2 to solve many of these identity challenges as you move to the cloud.  Additionally, I will also highlight how the Windows Identity Foundation (previously codenamed "Geneva" Framework), or WIF, is used to make your applications claims-aware and minimize the amount of work required by developers.

To explore ADFS v2 and WIF in more detail – and I strongly encourage you do! – please take a look at the following resources and blogs:

Now, before you go through this post and start building this solution for yourself, download the Windows Identity Foundation and Windows Azure Passive Federation code.  Run the executable; immediately after the code is installed/copied on to your machine a browser window will open and load the documentation.  Read the entire guide.  There is a ton of good information in the documentation.  Next, run through the whole guide and run the demos.  I’m not going to restate anything mentioned in the guide in this post, since the guide does a fabulous job.  This post assumes that you’ve gone through and leveraged the WIF & WA passive federation guide.

A few additional assumptions I’d like to call out:

  • You have an ADFS v2 server (today you’d use "Geneva" Server Beta 2).
  • You have installed Windows Identity Foundation.
  • You are running Visual Studio 2008 (although 2010 will probably work fine).
  • You have installed the Windows Azure SDK and Windows Azure Tools for Visual Studio.
  • You have a Windows Azure account and project.

Okay, let’s get started!

Building the Application

For a comprehensive examination of many of the below steps, please refer to the overview and walkthrough installed in the guide you installed above.  For the sake of brevity, I have focused on the execution of the process rather than a thorough explanation of how it works.  The guide provides a lot of valuable information.

1. To start, create your Windows Azure project.  I created a "Federated Identity Demo" pr
oject with the service name "fedid".  Be sure and keep track of the service name you choose, as you will use it when creating your certificate.

2. You must now create the certificate that you’ll use for SSL.  Open the folder where you installed the WIF & WA federation guide.  In this folder you will find a folder called assets.  Open a Visual Studio 2008 Command Prompt (choose to runas administrator) and run the command:

CreateCert.cmd <Azure Project service name>

For example, this is what I ran:

CreateCert.cmd

Note: you will have to enter the password "abc!123" multiple times.  This is documented in the guide.  Additionally, you will be prompted to install a certificate on your machine – click Yes.

Certification Authority

This process will create a number of files in the Assets folder, including:

  • fedid.cloudapp.net.cer
  • fedid.cloudapp.net.pfx
  • fedid.cloudapp.net.pvk
  • encoder.out

3. Create a new Visual Studio 2008 solution.  Add a Cloud Service project, and create a Web Role.

4. Update the ServiceDefinition.csdef file to update the following:

  • HTTPS protocol
  • Port 443
  • enableNativeCodeExecution: true

It should look like the following after the update:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="CloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="Web" enableNativeCodeExecution="true">
    <InputEndpoints>
      <!-- Must use port 80 for http and port 443 for https when running in the cloud -->
      <InputEndpoint name="HttpIn" protocol="https" port="443" />
    </InputEndpoints>
    <ConfigurationSettings />
  </WebRole>
</ServiceDefinition>

5. Right-click the Cloud Service project, and choose Properties.  Select the SSL tab.  Enable both checkboxes, and select the certificate you generated from the store.  Here’s what it looks like for me once I finished updating:

 SSL tab 

6. Add the following references to your Web Role project:

  • System.IdentityModel
  • Microsoft.IdentityModel
  • Microsoft.IdentityModelPlus (this is in the assets folder that was created by the guide)

Make sure to set Copy Local true for Microsoft.IdentityModel and Microsoft.IdentityModelPlus so that they are added to your Windows Azure package.

7. Create a Global.asax file.

8. Update the Global.asax file so that you have the following using statements:

using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel;
using Microsoft.IdentityModel.Configuration;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Web;
using Microsoft.IdentityModel.Web.Configuration;
using Microsoft.IdentityModelPlus.Configuration;
using Microsoft.IdentityModelPlus.Tokens;

9. Add the following "ServiceConfiguration_Created" method:

void ServiceConfiguration_Created(object sender, ServiceConfigurationCreatedEventArgs args)
{
    ServiceConfiguration configuration = args.ServiceConfiguration;
    List<CookieTransform> sessionTransforms = new List<CookieTransform>(new CookieTransform[]
    {
        new DeflateCookieTransform(), new MachineKeyProtectionTransform()
    });
    SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly(), new MruSecurityTokenCache());
    configuration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
    MicrosoftIdentityModelPlusSection plusConfiguration = MicrosoftIdentityModelPlusSection.Current;

    if (plusConfiguration != null && plusConfiguration.ServiceCertificate.ElementInformation.IsPresent)
    {
        X509Certificate2 serviceCertificate = plusConfiguration.ServiceCertificate.GetCertificate();
        SecurityToken serviceToken = new X509SecurityToken(serviceCertificate);
        SecurityTokenResolver serviceResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(
            new List<SecurityToken>(new SecurityToken[] { serviceToken }).AsReadOnly(), false);

        configuration.ServiceTokenResolver = serviceResolver;
    }
}

10. Add the following "WSFederationAuthenticationModule_RedirectingToIdentityProvider" method:

void WSFederationAuthenticationModule_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e)
{
    Uri reqUrl = Request.Url;
    StringBuilder wreply = new StringBuilder();
    wreply.Append(reqUrl.Scheme);     // e.g. "http"
    wreply.Append("://");
    wreply.Append(Request.Headers["Host"] ?? reqUrl.Authority);
    wreply.Append(Request.ApplicationPath);
    if (!Request.ApplicationPath.EndsWith("/"))
    {
        wreply.Append("/");
    }
    e.SignInRequestMessage.Reply = wreply.ToString();
}

11. Update the "Application_Start" method so that it creates event handlers for the two previous methods:

protected void Application_Start(object sender, EventArgs e)
{
    FederatedAuthentication.ServiceConfigurationCreated += this.ServiceConfiguration_Created;

    FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider +=
        new EventHandler<RedirectingToIdentityProviderEventArgs>(WSFederationAuthenticationModule_RedirectingToIdentityProvider);
}

12.  You must now make some significant updates to the Web.Config file.  This is probably the most challenging step, as it requires a number of updates.  While I will walk through the details of the updates below, I am also including a copy of my Web.Config file for your review on SkyDrive.  Please feel free to use it as a reference.  Also, please note that (for simplicity) the code shown below includes values that my demo uses.  You will have to update with your own values, and I have tried to call out where this is necessary.

13. Add the following to the <configuration><configSections> … </configSections></configuration>

<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<section name="microsoft.identityModelPlus" type="Microsoft.IdentityModelPlus.Configuration.MicrosoftIdentityModelPlusSection, Microsoft.IdentityModelPlus" requirePermission="false" />

14. Add the app key for the federation metadata location.  You will have to update this value with your own XML file published by your ADFS v2 server.

<appSettings>
  <add key="FederationMetadataLocation" value="https://corp2.sts.microsoft.com/FederationMetadata/2007-06/FederationMetadata.xml" />
</appSettings>

15. After connectionStrings, add the following location path.

<location path="FederationMetadata">
  <system.web>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>
</location>

16. Add the Microsoft.IdentityModel assembly.

<add assembly="Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

17. Configure the authorization and authentication.  You may have to change existing values.

<authorization>
  <deny users="?" />
</authorization>
<authentication mode="None" />

18. Add the WSFederationAuthenticationModule and SessionAuthenticationModule modules to <httpModules> … </httpModules>.

<add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

19. Add the WSFederationAuthenticationModule and SessionAuthenticationModule modules to <modules> … </modules>.

<add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
<add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />

20. Add the microsoft.identityModel section.

<microsoft.identityModel>
  <service>
    <audienceUris>
      <add value="https://fedid.cloudapp.net/" />
    </audienceUris>
    <federatedAuthentication>
      <wsFederation passiveRedirectEnabled="true" issuer="https://corp2.sts.microsoft.com/FederationPassive/" realm="https://fedid.cloudapp.net/" requireHttps="true" />
      <cookieHandler requireSsl="true" />
    </federatedAuthentication>
    <applicationService>
      <claimTypeRequired>
        <claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" optional="true" />
        <claimType type="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" optional="true" />
      </claimTypeRequired>
    </applicationService>
    <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <trustedIssuers>
        <add thumbprint="A4010FC094ECEDE6C94EDE36315ADB3EEC876C8A" name="CN=corp2.sts.microsoft.com, OU=IAM, O=Microsoft, L=Redmond, S=wa, C=US" />
      </trustedIssuers>
    </issuerNameRegistry>
  </service>
</microsoft.identityModel>

You will have to make a number of updates:

  • Update "fedid" in "https://fedid.cloudapp.net" to your Windows Azure service name.
  • Update the wsFederation issuer to your ADFS v2 issuer.
  • Update the wsFederation realm so that it uses your Windows Azure service name.
  • Ensure that the claimTypeRequired claimTypes are valid.
  • Update the trustedIssures so that you have your ADFS v2 thumbprint and name.  I did this by using tools that come with the Windows Identity Foundation tools.  You can right-click an existing ASP.NET Web site project and select "Modify STS Reference…".  This will launch the Federation Utility wizard, and will help construct pieces of the Web.Config.  On the second step, you can select "Use an Existing STS" and point it to your ADFS v2 endpoint.  The tool will then generate a lot of the configuration for you, including the trustedIssuers thumbprint and name (see the image below).

Federation Utility wizard

Note: this doesn’t need to be a publicly exposed ADFS server.  In fact, if you don’t have a production IP address to use, you can download one sample (simple) IP STS included in the code downloaded from http://claimsid.codeplex.com/.

21. You need to add the Microsoft.IdentityModelPlus section to the Web.Config file.  The CreateCert.cmd script you ran to generate the script has actually generated this section for you.  You can get it out of the encoder.out file in the assets folder.

<microsoft.identityModelPlus><serviceCertificate><certificate name="fedid.cloudapp.net" password="abc!123" encodedType="pfx" encodedValue="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" /></serviceCertificate></microsoft.identityModelPlus>

Note: this is only necessary because currently you cannot install certificates in Windows Azure.  Expect this to change in the future.

22. Finally, as a way of confirming that everything is working and that the claims you expect are actually sent to your application, update the Default.aspx.cs file so that you iterate through the claims and write them to the browser.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.IdentityModel.Claims;
using System.Threading;

namespace Web
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                IClaimsIdentity ici =
                    Thread.CurrentPrincipal.Identity as IClaimsIdentity;

                foreach (Claim c in ici.Claims)
                    Response.Write(c.ClaimType + " - " + c.Value + "<br/>");
            }
            catch (Exception ex)
            {
                Response.Write(ex.ToString());
            }
        }
    }
}

And that’s it!  Assuming that you have correctly followed the above steps, you’re ready to test!

Now, when you hit the endpoint on your ADFS v2 service, you will get redirected to https://fedid.cloudapp.net (or whatever your URL is) because that’s what you specified as the realm for your identity federation.  This means that, to test this locally, you need to update your hosts file so that fedid.cloudapp.net temporarily resolves locally.  Otherwise, it will redirect to the cloud.  I know we’ve spend years abhorring the hosts file, but sometimes it just works.

hosts

When you’re ready to run this in the cloud, simply package up your Windows Azure solution and publish.  Remember that you will only be able to successfully test this in production, as the staging account uses a GUID for the URL alias.  Also, if you’ve updated your hosts file, but sure and undo your changes so that you no longer resolve locally.

I hope you found this article valuable.  Good luck!

I had the pleasure to co-present with one of my fellow evangelists, Dave Bost, on architecting and developing with the ADO.NET Entity Framework this week.  I focused on application architecture topics while Dave focused on developing applications.

I think we can all agree – and if not, please let me know why – that the Entity Framework provides some awesome capabilities – mapping your conceptual schema to your data schema, isolation from the relational database and database schema, change tracking and identity resolution, full query comprehension and optimization, and more.  Yet, despite these features, it is difficult to figure out how and where to include the Entity Framework in your application architecture.

In preparation for this talk, I spent a lot of time looking at different strategies and architectures for using your data access layer (DAL) and the Entity Framework – or any O/RM tool, for that matter.  In the end, I settled on three approaches – certainly there are other patterns and approaches, but I found these to be the most relevant:

  1. Entity Framework as the DAL
  2. Full encapsulation of the Entity Framework
  3. Partial encapsulation of the Entity Framework

Let me spell it out in a little more detail, as well as highlight what I feel are the different pro’s and con’s.

Entity Framework as the Data Access Layer

With this approach, you opt to use the Entity Framework as your data access layer.  This is a perfectly legitimate approach, and comes with a host of benefits in many situations.  Here’s a picture of the architecture:

EF

As you can see, in this architecture aspects of the Entity Framework – like entities and the entity framework object context – are scattered throughout the various tiers.  This approach has many benefits, but it also introduces some challenges.

- Pro’s:

  • Excellent isolation from the DB schema
  • Independence from the relational database
  • Object services, namely identity and change tracking
  • Full query comprehension and optimization

- Con’s:

  • In .NET 3.5 SP1 the “object first” approach is not well supported (updated in EF 4.0)
  • Difficult to switch your O/RM, as you are tightly coupled to the Entity Framework
  • Limited support for data validation

If you aren’t offended by the scattering of your entities and entity contexts throughout your application tiers, then this is a perfectly valid architecture.  That said, most people probably recognize that technology changes, and an application that works perfectly well with Entity Framework today may need to move to a newer technology in the future.  Consequently, you may want to look at an approach that encapsulates the Entity Framework, so that you separate your concerns and have high cohesion in your tiers without tight coupling.

Full Encapsulation of the Entity Framework

There are many benefits to encapsulation.  We have talked and read about ensuring a separation of concerns – e.g. high cohesion, loose coupling – for years now, and for good reason.  Typically we want to reduce the tight coupling throughout application so that tools like Entity Framework don’t proliferate through all the tiers of our application.  This helps make our code more testable, and allows us to utilize techniques such as Inversion of Control and Dependency Injection.

At the same time, fully encapsulating a tool like Entity Framework also comes with some costs.  If the real value of this tool is the ability to empower developers to quickly build powerful applications that are fully optimized against your database, then full encapsulation may inhibit some of the capabilities.

- Pro’s:

  • Simplified queries
  • POCO objects
  • ORM & database agnostic
  • No references to Entity Framework
  • Isolation of SQL queries

- Con’s:

  • Loss of change tracking and identity management with Entity Framework
  • Additional object materialization of business objects
  • No query composition; simple LINQ enumeration queries

Again, this is not a full laundry list, but hopefully it provides some of the different benefits and challenges.  Fortunately, there’s a third path you can take, which is a hybrid of the two – I call this partial encapsulation.

Partial Encapsulation of the Entity Framework

When you decide to partially encapsulate the Entity Framework, you acknowledge the benefits of the separation of concerns and do what you can to loosely couple your tiers.  But you also try to preserve the advantages of a tool like the Entity Framework.  In this scenario, you might expose your entities to the different tiers of your application, but encapsulate the rest of the Entity Framework in your DAL.  When you return data from the DAL, you would simply use one of the three techniques: IEnumerable, IQueryable, or ObjectQuery.  Other than the last technique, you aren’t exposing aspects of the Entity Framework – other than the entities themselves – to any other tiers.  This preserves the loose coupling, but allows you to leverage the real value of the Entity Framework.

- Pro’s:

  • Query composition
  • Identity resolution & changing tracking
  • Some independence from O/RM tool

- Con’s:

  • Use of Entity Framework entities has implications on business layer
  • Lack of isolation of SQL queries – spread throughout the various tiers

Partial encapsulation is a pragmatic approach to this problem, and it’s a technique the I have seen many customers and partners utilize very successfully.  In the end, the approach you choose depends on your situation.  All three of these approaches are perfectly valid, but aren’t necessarily valid in every situation.

Below are the slides I used during the presentation.  I am sure that this is a presentation I’ll give again in the future, so expect to see updates and/or changes.

ADO.NET Entity Framework & Your Data Access Layer ame="allowFullScreen" value="true" />
View more documents from Wade Wegner.

I’d love to hear your feedback, so please leave me a comment or message.

I hope this helps!

Yesterday I gave a talk on .NET architecture to a very large customer here in Illinois (in case you’re interested, I had to drive down to Bloomington, IL. to visit them).  The description of the talk was pretty bland – “Overview of application architecture for medium to large scale applications.” – so I tried to spice it up a bit.  Here’s the presentation:

Ultimately, my goal in this talk was to address the following:

  • Provide an introduction to software architecture – i.e. the practice of architecture, the role of an architect, architecture patterns & anti-patterns, methodologies, and the like – to developers that typically live in a world of software implementation.
  • Explore the practical aspects of applying architectural practices in .NET.

I had a lot of fun preparing for this talk, and I sincerely hope that the audience found it valuable.  I hope to eventually record this as a webcast and then break off into more specific topics that dig into different areas.