将EF代理对象转换为原始POCO对象的最佳方法是什么?

Gar*_*ill 5 c# asp.net-mvc-4 asp.net-web-api entity-framework-5

我有一些POCO对象,我在EF Code First上下文中使用.所以,当我用数据填充它们时,我实际上是处理EF代理对象而不是POCO本身.

我有一个ASP.NET MVC4 ApiController,它返回我的POCO对象,我将在客户端应用程序中使用它.

我的"GET"方法看起来像这样:

    // GET api/Clients/5
    public Client GetClient(int id)
    {
        Client client = db.Clients.Find(id);
        if (client == null)
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
        }

        return client;
    }
Run Code Online (Sandbox Code Playgroud)

这实际上不起作用,因为当序列化程序尝试序列化Client对象时,它实际上正在处理EF代理版本,这导致它打嗝.请参阅ApiController可以返回带有其他对象集合的对象吗?

所以,我可以通过这样做来关闭代理生成DbContext:

    db.Configuration.ProxyCreationEnabled = false;
Run Code Online (Sandbox Code Playgroud)

这确保我正在处理POCO而不是代理.但是,现在我的Client类的大多数成员都没有填充,因为它是EF代理,它懒得加载那些对我来说.

所以我真正想要的是使用EF代理类来获取数据,然后在最后一刻从我的方法返回原始POCO.

如果不在代码中手动创建整个对象(包括任何嵌套对象),我该怎么做?当然必须有一个简单的方法 - 或者至少是某种帮助类?

cuo*_*gle 3

您的问题涉及如何设计应用程序的架构。从技术上讲,一个应用程序中有多个模型:域模型、数据传输对象或视图模型,用于不同的层:业务逻辑层、分布层和表示层。

在 ASP.NET MVC 中滥用模型,我经常看到使用域模型(来自 EF)作为视图模型,因为在某些情况下,域模型作为视图模型足以满足您的 UI 需求,这是正确的。但实际上这是完全不同的,对于复杂的 UI,例如:网格,可能需要多个域模型组合在一个视图模型中来为您的 UI 提供数据。

与分发层、asp.net web api 类似,消费者可能需要多个域模型来完成某件事。通常不是100%领域模型作为数据传输对象。

因此,为了分离关注点,建议您应该创建 DTO 对象并将其与域对象(来自 EF 的 POCO 对象)分开,即使它在属性中按 1:1 映射。

例如,如果您有 Customer 域模型,则需要有 CustomerDto。

您可以手动映射或使用AutoMapper等工具将域模型映射到 DTO 模型。

通过这种方式,您还可以避免出现问题。

  • +1 将 DTO 暴露给远程客户端是最好的方法。它使您可以完全控制通过线路发送的数据。 (2认同)