Compartilhar via


Este artigo foi traduzido por máquina.

Aplicativos com várias camadas e o Entity Framework

Criando aplicativos com várias camadas com o EF4

Daniel Simmons

Baixar o código de exemplo

Este artigo é o terceiro de uma série sobre nde -camada de programação com o Entity Framework (consulte do msdn.microsoft.com/magazine/dd882522.aspx e msdn.microsoft.com/magazine/ee321569.aspx ), especificamente sobre a criação de serviços Web personalizados com o Entity Framework (FE) e Windows Communication Foundation (WCF). (Em algumas situações, um serviço baseado em REST ou outra abordagem é apropriada, mas esses artigos me tiver concentrei em serviços Web personalizados.) O primeiro artigo descrito um número de design importantes considerações e antipatterns. No segundo artigo, escrevi sobre quatro padrões podem ser usados com êxito em um n -camada de aplicativo. Esse artigo também incluído amostras de código que ilustram como o primeiro lançamento da Entity Framework (EF 3.5 SP1) pode ser usado para implementar que chamo o padrão de entidades simples. Neste artigo, examinarei alguns recursos que virão na segunda versão da estrutura de entidades (EF4) e como usá-los para implementar Self-Tracking Entities e objetos de transferência de dados (DTOs) n - camada padrões.

Enquanto entidades simples geralmente não é o padrão preferencial para nde -camada de aplicativos, é a opção mais viável na primeira versão do EF.  EF4, entretanto, altera significativamente as opções de n -camada com a estrutura de programação.  Alguns dos principais novos recursos incluem o seguinte:

  1. Desconectado de novos métodos do framework que suportam operações, tais como ChangeObjectState e ChangeRelationshipState, alterar uma entidade ou relacionamento para um novo estado (adicionado ou modificado, por exemplo); ApplyOriginalValues, que permite que você defina os valores originais para uma entidade; e o novo evento ObjectMaterialized, que é acionado sempre que uma entidade é criada pela estrutura.
  2. Suporte para valores de chave externa em entidades e POCO (Plain Old CLR Objects). Esses recursos permitem que você criar classes de entidade que podem ser compartilhados entre a implementação de serviço mid-tier e outras camadas, que pode não ter a mesma versão do Entity Framework (.NET 2.0 ou Silverlight, por exemplo). Objetos POCO com chaves estrangeiras também tem um formato de serialização simples que simplifica a interoperabilidade com plataformas como Java. O uso de chaves estrangeiras também permite que um modelo de simultaneidade muito mais simples para relações.
  3. T4 modelos para personalizar a geração de código. Esses modelos fornecem uma maneira para gerar classes Implementando Self-Tracking entidades ou DTOs padrões.

A equipe do Entity Framework usou esses recursos para implementar o padrão de Self-Tracking entidades em um modelo, tornando esse padrão muito mais acessíveis e enquanto ainda DTOs requerem mais trabalho durante a implementação inicial, esse processo também é mais fácil com EF4. (Modelo Self-Tracking Entities e alguns outros recursos EF estão disponíveis como parte de uma Web baixar visualização de tecnologia da comunidade de recurso (CTP), em vez de no Visual Studio 2010/.NET 4 caixa. Os exemplos neste artigo presumem que o Visual Studio 2010/.NET 4 e o CTP do recurso são instalados.) Com esses novos recursos, uma maneira de avaliar quatro padrões que descrevi (entidades simples, alterar conjunto, Self-Tracking Entities e DTOs) é em termos de uma compensação entre benção arquitetura (separação de preocupações/soltos acoplamento força do contrato, formato de conexão eficiente e interoperabilidade) e facilidade de implementação e tempo de mercado. Se você plotar quatro padrões em um gráfico que representa essa compensação, o resultado pode parecer algo como do Figura 1.


Figura 1 NComparando -camada padrões com EF4

O direito padrão para uma determinada situação depende muito de fatores. Em geral, DTOs oferecem muitas vantagens arquiteturais um custo de implementação inicial alto. Alterar conjunto apresenta algumas características de arquiteturais boas, mas é fácil de implementar (ele está disponível para uma tecnologia específica — por exemplo, o DataSet no ADO.NET tradicionais).

Recomendo um equilíbrio entre essas preocupações iniciando com entidades Self-Tracking e movendo para DTOs se a situação justifica isso pragmatic/ágil. Freqüentemente, você pode obter em funcionamento rapidamente com entidades Self-Tracking e ainda atingir muitas metas arquiteturais importantes. Essa abordagem representa uma compensação muito melhor do que alterar conjunto ou Entities simples, de qual recomendo somente se você tiver outras opções viáveis. DTOs, por outro lado, são definitivamente a melhor opção como seu aplicativo se torna maior e mais complexa ou se você tiver requisitos não podem ser atendidos pelo Self-Tracking Entities, como diferentes taxas de alteração entre o cliente e o servidor. Esses dois padrões são as ferramentas mais importantes para ter sua caixa de ferramentas, portanto let’s dê uma olhada cada uma delas.

Entidades self-Tracking

Para usar esse padrão com o Entity Framework, comece criando um modelo de dados de entidade que representa seus entidades conceituais e mapear para um banco de dados. Você pode reverter a engenharia um modelo de um banco de dados têm e personalizá-lo, ou você pode criar um modelo a partir do zero e gerar um banco de dados para coincidir (outro novo recurso EF4). Depois que este modelo e mapeamento estiverem no lugar, substitua o modelo de geração de código padrão com o modelo de entidades Self-Tracking clicando com o botão direito do mouse na superfície do designer de entidade e escolhendo Add Item de geração de código.

Em seguida, escolha o modelo de entidades Self-Tracking da lista de modelos instalados. Esta etapa desativa padrão geração de código e adiciona dois modelos para seu projeto: um modelo gera o ObjectContext e o modelo gera classes de entidade. Separando a geração de código em dois modelos torna possível dividir o código em assemblies separados, um para classes de entidade e um para seu contexto.

A principal vantagem dessa abordagem é que você pode ter suas classes de entidade em um assembly não tem dependências no Entity Framework. Dessa forma, o assembly de entidade (ou pelo menos código que ele gera) e qualquer lógica de negócios implementou existe pode ser compartilhada pelo mid-tier e o cliente se você desejar. O contexto é mantido em um assembly que possui dependências em entidades e o EF. Se o cliente do seu serviço está executando o .NET 4, você pode apenas referenciar o assembly de entidade do projeto cliente. Se seu cliente está executando uma versão anterior do .NET ou executa o Silverlight, você provavelmente deseja adicionar links de projeto de cliente para os arquivos gerados e recompilar a fonte de entidade que projeto (direcionamento CLR apropriado).

Independentemente de como estruturar seu projeto, os dois modelos funcionam juntos para implementar o padrão de entidades Self-Tracking. As classes de entidade gerado são classes POCO simples cujo único recurso além do armazenamento básico das propriedades de entidade é controlar as alterações para as entidades de — o estado geral de uma entidade, altera a propriedades críticas, como tokens de simultaneidade e alterações nas relações entre entidades. Essas informações de rastreamento extra são parte da definição do DataContract para as entidades (portanto, quando você enviar uma entidade ou para um serviço WCF, as informações de rastreamento são executadas junto).

No cliente do serviço, as alterações para as entidades são controladas automaticamente, embora as entidades não estão associadas a qualquer contexto. Cada entidade gerada possui código como o seguinte para cada propriedade. Se você alterar um valor de propriedade em uma entidade com o estado inalterado, por exemplo, o estado é alterado modificado:

[DataMember]
public string ContactName
{
    get { return _contactName; }
    set
    {
            if (!Equals(_contactName, value))
            {
                _contactName = value;
                OnPropertyChanged("ContactName");
            }
    }
}
private string _contactName;

Da mesma forma, se novas entidades são adicionadas a um gráfico ou entidades são excluídas de um gráfico, que informações são rastreadas. Desde que o estado de cada entidade é controlado na própria entidade, o mecanismo de controle se comporta como você esperaria mesmo quando você relacionar entidades recuperados de mais de uma chamada de serviço. Se você estabelecer uma nova relação, apenas a alteração é rastreada — as entidades envolvidas permanecer no mesmo estado, como se eles tinham todos sido recuperados de uma chamada de serviço único.

O modelo de contexto adiciona um novo método ApplyChanges, o contexto gerado. ApplyChanges anexa um gráfico de entidades para o contexto e define as informações ObjectStateManager para coincidir com as informações controladas em entidades. Com as informações que as entidades controlar sobre si mesmos e ApplyChanges, o código gerado manipula ambos alterar preocupações de simultaneidade e rastreamento, duas das partes mais difíceis de implementar corretamente um n - camada solução.

Como um exemplo concreto, do Figura 2 mostra um ServiceContract simples que você poderia usar com entidades Self-Tracking para criar um n - camada ordem envio sistema baseado no banco de dados de exemplo Northwind.

Figura 2 de um contrato de serviço simples para o padrão de entidades Self-Tracking

[ServiceContract]
public interface INorthwindSTEService
{
    [OperationContract]
    IEnumerable<Product> GetProducts();

    [OperationContract]
    Customer GetCustomer(string id);

    [OperationContract]
    bool SubmitOrder(Order order);

    [OperationContract]
    bool UpdateProduct(Product product);
}

O método GetProducts do serviço é usado para recuperar dados de referência no cliente sobre o catálogo de produtos. Essas informações geralmente cache localmente e geralmente não são atualizadas no cliente. GetCustomer recupera um cliente e uma lista de pedidos do cliente.  A implementação desse método é bem simples, como mostrado aqui:

public Customer GetCustomer(string id)
{
    using (var ctx = new NorthwindEntities())
    {
        return ctx.Customers.Include("Orders")
        .Where(c => c.CustomerID == id)
        .SingleOrDefault();
    }
}

Isso é essencialmente o mesmo código que você escreveria uma implementação desse tipo de método com o padrão de entidades simples. A diferença é que as entidades sendo retornadas são self-tracking, que significa que o código de cliente para usar esses métodos também é bem simples, mas pode fazer muito mais.

Para ilustrar, let’s supor que no processo de envio ordem você deseja não apenas para criar um pedido com ordem apropriada linhas de detalhes, mas também para atualizar partes da entidade customer com as informações de contatos mais recentes. Além disso, você deseja excluir quaisquer ordens que tenham um DataDoPedido nulo (talvez o sistema marca pedidos rejeitados dessa maneira). Com o padrão de entidades simples, a combinação de adicionando, modificando e excluindo entidades em um único gráfico exigiria várias chamadas de serviço para cada tipo de operação ou um contrato personalizados muito complicado e implementação de serviço se você tentou implementar algo como Self-Tracking entidades na primeira versão do EF. Com EF4, o código cliente pode parecer do Figura 3.

Figura 3 do código de cliente para o padrão de entidades Self-Tracking

var svc = new ChannelFactory<INorthwindSTEService>(
    "INorthwindSTEService")
    .CreateChannel();

var products = new List<Product>(svc.GetProducts());
var customer = svc.GetCustomer("ALFKI");

customer.ContactName = "Bill Gates";

foreach (var order in customer.Orders
    .Where(o => o.OrderDate == null).ToList())
{
    customer.Orders.Remove(order);
}

var newOrder = new Order();
newOrder.Order_Details.Add(new Order_Detail()
    {
        ProductID = products.Where(p => p.ProductName == "Chai")
                    .Single().ProductID,
        Quantity = 1
    });
customer.Orders.Add(newOrder);

var success = svc.SubmitOrder(newOrder);

Esse código cria o serviço, chama os dois primeiros métodos para obter a lista de produtos e uma entidade de cliente e faz alterações ao gráfico de entidade de cliente usando o mesmo tipo de código que você escreveria se estavam criando um aplicativo de Entity Framework de duas camadas falou diretamente para o banco de dados ou foram Implementando um serviço no mid-tier. (Se não estiver familiarizado com esse estilo de criação de um cliente de serviço do WCF, ele cria automaticamente um proxy de cliente para você sem criar proxies para entidades, pois estamos são reutilizar as classes de entidade do modelo de entidades Self-Tracking. Você também pode usar o cliente gerado pelo comando Add Service Reference no Visual Studio se desejar.) Mas aqui, não há nenhum ObjectContext envolvido. Você apenas estiver manipulando entidades próprios. Finalmente, o cliente chama o método de serviço SubmitOrder para empurrar as alterações de para o mid-tier.

Claro, em um aplicativo real alterações do cliente ao gráfico provavelmente seriam provenientes de uma interface de algum tipo e seria adicionar tratamento de chamadas de serviço (especialmente importantes quando você tiver se comunicar pela rede) de exceção, mas o código no do Figura 3 ilustra os princípios. Outro item importante a observar é que quando você criar a entidade de detalhes do pedido para a nova ordem, você definir apenas a propriedade ProductID em vez da entidade de produto. Este é o novo recurso de relação de chave externa em ação. Reduz a quantidade de informações que trafegam durante a transmissão porque serializar apenas o ProductID para mid-tier, não uma cópia da entidade do produto.

É na implementação do método de serviço SubmitOrder Self-Tracking entidades realmente brilha:

public bool SubmitOrder(Order newOrder)
{
    using (var ctx = new NorthwindEntities())
    {
        ctx.Orders.ApplyChanges(newOrder);
        ValidateNewOrderSubmission(ctx, newOrder);
        return ctx.SaveChanges() > 0;
    }
}

A chamada para ApplyChanges realiza a mágica. Ele lê as informações de alteração das entidades e aplica o contexto de uma maneira que torna o resultado o mesmo como se tivessem sido executadas essas alterações no entidades anexadas ao contexto de todo o tempo.

Validando alterações

Algo que deve observar na implementação SubmitOrder é chamada para ValidateNewOrderSubmission. Esse método, adicionei a implementação de serviço, examina ObjectStateManager para certificar-se de que somente os tipos de alterações que esperamos em uma chamada para SubmitOrder estão presentes.

Essa etapa é realmente importante porque por si só, ApplyChanges envia quaisquer alterações localiza em um gráfico inteiro de objetos relacionados para o contexto. Nossa expectativa de que o cliente irá apenas adicionar novos pedidos, atualizar o cliente e assim por diante não significa que um cliente com bugs (ou até mesmo mal-intencionado) não faria algo. Se ele alterado o preço de um produto para tornar uma ordem mais barato ou mais cara do que ele deve ser? Os detalhes de como a validação é executada são menos importantes que a regra crítica que você sempre deve validar alterações antes de salvar para o banco de dados. Esta regra se aplica independentemente de n - camada padrão você usar.

Um segundo princípio de design fundamental é que você deve desenvolver métodos de serviço separada, específica para cada operação. Sem essas operações separadas, você não tiver um contrato de alta segurança que representa o que é e não é permitido entre as duas camadas e validar corretamente suas alterações pode se tornar impossível. Se você tivesse um método de serviço SaveEntities único em vez de um SubmitOrder e um método separado UpdateProduct (somente acessível por usuários autorizados para modificar o catálogo do produto), você poderia facilmente implementar a aplicação e salvar parte desse método, mas seria não é possível validar adequadamente porque você não teria como saber quando são permitidas atualizações de produto e quando eles não são.

Objetos de transferência de dados

O padrão de entidades Self-Tracking torna de n -camada processo fácil, e se você cria métodos de serviço específico e valida cada um, ele pode ser bastante som arquitetura. Mesmo assim, há limites que você pode fazer com o padrão. Ao executar esses limites, DTOs são a maneira da dilema.

DTOs, em vez de compartilhar uma única entidade implementação entre o cliente e o mid-tier você cria um objeto personalizado que é usado apenas para transferir dados através do serviço e desenvolver implementações de entidade separada para o cliente e o mid-tier. Essa alteração fornece dois benefícios principais: Ele isola seu contrato de serviço de problemas de implementação no cliente, permitindo que contrato permanecer estável, mesmo se a implementação de alterações de camadas e permite que você controle os dados que fluem durante a transmissão e o mid-tier. Portanto, você pode evitar o envio de dados (ou o cliente não tem permissão para acessar dados) desnecessários ou reformatar os dados para tornar mais conveniente para o serviço. Geralmente, o contrato de serviço foi desenvolvido com os cenários de cliente em mente para que os dados podem ser reformatados entre entidades mid-tier e DTOs (talvez por combinar várias entidades em um DTO e ignorando as propriedades necessárias não no cliente), enquanto os DTOs pode ser usado diretamente no cliente.

Esses benefícios, entretanto, vêm com o preço de ter que criar e manter um ou dois mais camadas de objetos e mapeamento. Para estender o exemplo de envio do pedido, você poderia criar uma classe apenas para a finalidade de enviar novos pedidos. Essa classe combinaria propriedades da entidade customer com propriedades da ordem são definidas no novo cenário ordem, mas a classe deixaria out propriedades as duas entidades computadas no mid-tier ou definir outros estágio no processo. Isso torna o DTO como pequeno e eficiente possível. A implementação pode ter esta aparência:

public class NewOrderDTO
{
    public string CustomerID { get; set; }
    public string ContactName { get; set; }
    public byte[] CustomerVersion { get; set; }
    public List<NewOrderLine> Lines { get; set; }
}

public class NewOrderLine
{
    public int ProductID { get; set; }
    public short Quantity { get; set; }
}

Certo, isso é realmente duas classes — um para a ordem e um para as linhas de detalhes do pedido — mas o tamanho dos dados é mantido menor possível. A única aparentemente informações irrelevantes no código são o campo CustomerVersion, que contém as informações de versão de linha usadas para verificações de simultaneidade na entidade cliente. Essas informações necessárias para a entidade customer porque a entidade já existe no banco de dados. Para as linhas de ordem e detalhe, essas são novas entidades sendo enviadas para o banco de dados, portanto o OrderID e suas informações de versão não são necessários — são gerados pelo banco de dados quando as alterações são persistentes.

O método de serviço que aceita essa DTO usa o mesmo nível inferior Entity Framework APIs que usa o modelo de entidades Self-Tracking para realizar suas tarefas, mas agora você precisa chamar essas APIs diretamente, em vez de deixar que o código gerado chamar para você. A implementação vem em duas partes. Primeiro, crie um gráfico do cliente, a ordem e a ordem de entidades de detalhes com base nas informações o DTO (consulte do Figura 4).

Figura 4 Criando um gráfico de entidades

var customer = new Customer
    {
        CustomerID = newOrderDTO.CustomerID,
        ContactName = newOrderDTO.ContactName,
        Version = newOrderDTO.CustomerVersion,
    };

var order = new Order
    {
        Customer = customer,
    };

foreach (var line in newOrderDTO.Lines)
{
    order.Order_Details.Add(new Order_Detail
        {
            ProductID = line.ProductID,
            Quantity = line.Quantity,
        });
}

Em seguida, anexar o gráfico para o contexto e definir as informações de estado apropriado:

ctx.Customers.Attach(customer);
var customerEntry = ctx.ObjectStateManager.GetObjectStateEntry(customer);
customerEntry.SetModified();
customerEntry.SetModifiedProperty("ContactName");

ctx.ObjectStateManager.ChangeObjectState(order, EntityState.Added);
foreach (var order_detail in order.Order_Details)
{
    ctx.ObjectStateManager.ChangeObjectState(order_detail, 
       EntityState.Added);
}

return ctx.SaveChanges() > 0;

A primeira linha anexa o gráfico inteiro para o contexto, mas quando isso ocorre, cada entidade está em estado Unchanged, portanto, primeiro você informar ObjectStateManager para colocar a entidade do cliente no estado modificado, mas com apenas uma propriedade, ContactName, marcadas como modificadas. Isso é importante porque você não tiver realmente todas as informações do cliente — apenas as informações que foi o DTO. Se você tiver marcado todas as propriedades como modificado, o Entity Framework seria tente persistir um monte de nulos e zeros para outros campos da entidade customer.

Em seguida você pode alterar o estado do pedido e cada um dos seus detalhes de pedido adicionada e, em seguida, chamar SaveChanges.

Ei, onde está o código de validação? Nesse caso, porque você tem um DTO muito específico para seu cenário e são interpretar esse objeto como mapear informações de ele em suas entidades, você executar a validação como ir. Não há nenhuma maneira que esse código poderia inadvertidamente alterar o preço de um produto porque você nunca tocar a entidade do produto. Este é outro benefício do padrão DTO, mas apenas de forma rotatória. Você ainda terá que fazer o trabalho de validação; o padrão apenas força um nível de validação. Em muitos casos, seu código precisa incluir validação adicional de valores ou outras regras de negócios.

Uma consideração corretamente é tratamento de exceções de concorrência. Como mencionei anteriormente, as informações de versão para a entidade do cliente estão incluídas no DTO, portanto, configurar adequadamente detectar problemas de simultaneidade se alguém modifica o mesmo cliente. Um exemplo mais completo seria ou mapear essa exceção para uma falha WCF para que o cliente pode resolver o conflito ou seria capturar a exceção e aplicar algum tipo de diretiva automática para tratar o conflito.

Estender a amostra ainda mais adicionando outra operação, como a capacidade de modificar um pedido, você criaria outro DTO especificamente para esse cenário, com apenas as informações corretas para ele.  Este objeto seria algo como nosso NewOrderDTO mas teria propriedades NúmeroDoPedido e Version para a ordem e entidades de detalhes do pedido, bem como cada propriedade que você deseja permitir que a chamada de serviço para atualizar. A implementação de método de serviço também seria semelhante ao método SubmitOrderDTO mostrado anteriormente — percorrendo dados DTO, criando objetos de entidade correspondente e definindo seu estado no Gerenciador de estado antes de salvar as alterações no banco de dados.

Se você implementar o método de atualização de ordem tanto com entidades Self-Tracking e objetos de transferência de dados, você encontraria que a implementação de entidades Self-Tracking reutiliza as entidades e compartilhamentos quase todos os mesmos serviço código de implementação entre ele e o novo método de envio do pedido — a única diferença seria o código de validação e até mesmo alguns dos que podem ser compartilhadas. Implementação DTO, entretanto, requer uma classe de objeto de transferência de dados separada para cada um dos métodos de dois serviço e implementações do método siga padrões similares, mas tem muito pouco se qualquer código que pode ser compartilhado.

Dicas das trincheiras

Aqui estão algumas dicas para o que atento e compreender.

  • Certifique-se a reutilização entidade gerado código do modelo Self-Tracking Entity em seu cliente. Se você usar código proxy gerado pelo Add Service Reference no Visual Studio ou alguma outra ferramenta tudo certo parte, mas você descobrirá que as entidades não realmente manter controle das suas alterações no cliente.
  • Criar uma nova instância de ObjectContext em uma instrução using para cada método de serviço para que ele é descartado antes do método retorna. Esta etapa é crítica para a escalabilidade do seu serviço. Torna-se de que conexões de banco de dados não são mantidas abertas entre chamadas de serviço e estado temporário usado por uma determinada operação é lixo coletado quando operação é longo. O Entity Framework automaticamente armazena metadados e outras informações que precisa no domínio de aplicativo e ADO.NET pools banco de dados conexões, portanto, recriar o contexto de cada vez que é uma operação rápida.
  • Uso novas relações de chaves estrangeiras recurso sempre que possível.  Faz a alteração relações entre entidades muito mais fácil. Com associações independentes — o único tipo de relação disponível na primeira versão do Entity Framework — são executadas verificações de simultaneidade em relações independentemente das verificações de simultaneidade executadas em entidades e não há nenhuma maneira opt dessas verificações de simultaneidade de relacionamento. O resultado é que seus serviços devem executar os valores originais dos relacionamentos e defini-las no contexto antes de alterar os relacionamentos. Com relações de chave externa, porém, a relação é simplesmente uma propriedade da entidade e se a entidade passa sua verificação de simultaneidade, nenhuma seleção é necessária. Você pode alterar um relacionamento apenas alterando o valor da chave estrangeira.
  • Cuidado EntityKey colisões ao anexar um gráfico a um ObjectContext. Se, por exemplo, você está usando DTOs e partes do seu gráfico representam recém-adicionado entidades para o qual os valores de chave de entidade não tem sido definidos porque eles serão gerados no banco de dados, você deve chamar o método 
AddObject adicione primeiro o gráfico inteiro de entidades e alterar entidades não está no estado adicionada ao seu estado pretendido vez chamando o método Attach e alterando adicionado entidades a esse estado. Caso contrário, quando você chamar primeiro Attach, a Entity Framework acha que cada entidade deve ser colocada em estado Unchanged, que pressupõe que os valores de chave de entidade finais. Se mais de uma entidade de um determinado tipo tem o mesmo valor de chave (por exemplo, 0), o Entity Framework lançará uma exceção. Iniciando com uma entidade no estado adicionada, evitar esse problema porque a estrutura não espera adicionada entidades ter valores de chave exclusivos.
  • Desativar automático preguiçoso carregando (outro novo EF4 recurso) quando retornar entidades de métodos de serviço. Se você não o serializador irá disparar o carregamento lento e tentar recuperar entidades adicionais do banco de dados, o que fará com que mais dados que se destina a ser retornado (se suas entidades completamente estiverem conectadas, você pode serializar todo o banco de dados), ou, mais provavelmente, você receberá um erro porque o contexto será ser descartado antes o serializador tenta recuperar os dados. Self-Tracking entidades não tem o carregamento lento ativado por padrão, mas se você estiver criando uma solução DTOs, isso é algo atento.

E no fim

O .NET 4 lançamento da Entity Framework torna a criação de arquitetura som de n - camada de aplicativos muito mais fácil. Para a maioria dos aplicativos, recomendo iniciando com o modelo Self-Tracking entidades, que simplifica o processo e habilita a maioria dos reutilização. Se você tiver diferentes taxas de alteração entre cliente e serviço, ou se você precisar absoluto controle sobre seu formato de conexão, você deve mover para uma implementação de objetos de transferência de dados. Independentemente de qual padrão que você escolher, sempre tenha em mente os princípios de chaves que representam antipatterns e padrões — e nunca esquecer validar dados antes de salvar.

Daniel Simmons é um arquiteto na equipe da Entity Framework da Microsoft.