0

我正在使用 EF 和 WCF。我想使用 EF 生成的对象作为从 Web 服务方法返回的对象。在 OperationContract 方法中,我执行以下操作:

try
{
   b = (from bon in this.znDbContext.BonSet
        where bon.IdPr == pa.IdPr
        select bon).First();    
}
catch (InvalidOperationException) { }

return b;

如果我调用 Web 服务方法,我将收到以下错误消息:

调用服务失败。可能原因:服务离线或无法访问;客户端配置与代理不匹配;现有代理无效。有关更多详细信息,请参阅堆栈跟踪。您可以尝试通过启动新代理、恢复到默认配置或刷新服务来恢复。

在谷歌上搜索我找到了解决这个问题的解决方案。此声明已添加:

this.znDbContext.Configuration.ProxyCreationEnabled = false;

以这种方式,客户端从 Web 服务方法接收响应,但每个内部对象都有空值。如果我删除前面的语句并执行对象的副本(逐个字段),客户端会收到正确设置内部对象的对象(即 boni.User)。例如我这样做:

boni = new Bon();
User u = new User();
boni.IdPr = b.IdPr;
boni.Date = b.Date;
boni.System = b.System;
u.Id = b.User.Id;
u.Name = b.User.Name;
u.Login = b.User.Login;
boni.User = u;
return boni;

有没有一种方法可以返回一个包含所有内部对象的完整对象,而无需执行类似“克隆”操作的操作?我想要从 DbContext 中分离对象以获得一个新对象,从而避免手动复制操作。

对问题原因的理论解释非常受欢迎。

4

1 回答 1

3

当您将 ORM 代理与 DTO 混淆时,此问题是设计使然。这个问题/解决方案在 WCF 中很常见,也适用于任何其他 ORM,例如 nHibernate。

如果您从 ORM 获取实体,它通常会返回一个代理,该代理能够从数据库中延迟加载数据。例如,它只会在您第一次访问某个属性时加载它的实际数据。这意味着,如果您从 EM 获取“Bon”对象,它将为您提供“BonProxy”对象。显然,DataContract 中不需要“BonProxy”(您也不能将其传递给客户端,因为您将无法进一步延迟加载客户端)

解决方案: 将您的复杂实体转换为 DTO(即进行字段到字段的复制),然后通过网络发送 DTO。这对于序列化也是必要的——您可以控制它以避免循环引用。

于 2013-04-29T21:38:18.820 回答