我正在使用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服务方法,我将收到以下错误消息:
无法调用该服务。可能的原因:服务处于脱机状态 或无法进入;客户端配置与 代理;现有代理无效。请参阅堆栈跟踪 更多详情。您可以尝试通过启动新代理进行恢复,然后进行恢复 默认配置或刷新服务。
在Google上搜索我找到了解决此问题的解决方案。此声明已添加:
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中分离对象以获取一个新对象,避免手动复制操作。
对这个问题的理由进行理论解释是非常受欢迎的。
答案 0 :(得分:3)
当您将ORM代理与DTO混合时,此问题是设计使然。此问题/解决方案在WCF中很常见,也适用于任何其他ORM,例如nHibernate。
如果从ORM获取实体,它通常会返回一个能够从数据库延迟加载数据的代理。例如,它只会在您第一次访问属性时加载属性的实际数据。 这意味着,如果您从EM获取“Bon”对象,它将为您提供“BonProxy”对象。显然,DataContract中不会出现“BonProxy”(并且您也无法将其传递给客户端,因为您无法进行任何进一步的延迟加载客户端)
解决方案: 将您的复杂实体转换为DTO (即进行字段到字段复制),然后通过网络发送DTO。这对于序列化也是必要的 - 您可以控制它以避免循环引用。