如何将EF代理对象转换为原始POCO对象的最佳方法?

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;
    }

那种方法实际上是行不通的,因为当序列化器试图序列化客户端对象时,它实际上正在处理EF代理版本,这会导致出现问题。请参见Can an ApiController return an object with a collection of other objects?

所以,我可以通过对我的DbContext执行以下操作来关闭代理生成:

    db.Configuration.ProxyCreationEnabled = false;

这确保我处理的是POCO而不是代理。但是,现在我的客户端类的大部分成员都没有填充,因为它是EF代理,可以懒加载那些信息。

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

我如何在不手动从头开始创建整个对象(包括任何嵌套对象)的情况下实现呢?肯定有一种简单的方法 - 或者至少有某种帮助类吧?

2个回答

3
您的问题涉及如何为应用程序设计架构。从技术上讲,在一个应用程序中有多个模型:领域模型、数据传输对象或视图模型,适用于不同层次:业务逻辑层、分发层和表示层。
在ASP.NET MVC中误用模型,我经常看到使用领域模型(来自EF)作为视图模型,因为在某些情况下,将领域模型作为视图模型是足够的。但实际上它是非常不同的,对于复杂的UI,例如网格,可能需要多个领域模型组合成一个视图模型来为您的UI提供数据。
与分发层类似,asp.net web api,消费者可能需要多个领域模型来完成某些任务。通常不是100%的领域模型作为数据传输对象。
因此,为了关注点分离,建议您创建并分离DTO对象和域对象(来自EF的POCO对象),即使在属性中1:1映射。
例如,如果您有客户端领域模型,则需要具有CustomerDto。
您可以手动映射或使用像AutoMapper这样的工具将您的领域模型映射到DTO模型。
通过这种方式,您也可以避免问题。

2
将DTO暴露给远程客户端是最好的选择。这样可以完全控制通过网络发送的数据。 - Wiktor Zychla
谢谢,我会去看看AutoMapper - 它听起来就像是我正在寻找的“某种帮助类”。 - Gary McGill

1

我知道你已经得到了答案,但是也许你想看一下这个:

POCO代理类型不能直接由Windows Communication Foundation (WCF)序列化或反序列化,因为DataContractSerializer序列化引擎只能序列化和反序列化已知类型。代理类型不是已知类型。有关详细信息,请参阅“使用POCO实体”主题中的“序列化POCO代理”部分。要将POCO代理序列化为POCO实体,请在序列化期间使用ProxyDataContractResolver类将代理类型映射到POCO类型。

http://msdn.microsoft.com/en-us/library/vstudio/ee705457(v=vs.100).aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接