【问题标题】:Serialization POCO proxy with WCF使用 WCF 序列化 POCO 代理
【发布时间】:2012-02-12 15:13:15
【问题描述】:

当我运行我的服务时出现异常:

服务器在处理请求时遇到错误。异常消息是“无法序列化 System.Data.Entity.DynamicProxies.Cosik_14C2 类型的参数...”(对于操作“GetCosik”,合同“ICosikService”),因为它不是确切的类型“Project.Domain.Entities.Cosik” ' 在方法签名中并且不在已知类型集合中。为了序列化参数,使用 ServiceKnownTypeAttribute.' 将类型添加到已知类型集合以进行操作。有关详细信息,请参阅服务器日志。

我是 WCF 服务和实体框架的新手,如果有任何帮助/建议,我将不胜感激。

我正在使用实体框架 4.1。我使用代码优先创建了包含两个表的数据库:

[DataContract(IsReference=true)]
public class Cosik
{
    [DataMember]
    public int cosikID { get; set; }

    [DataMember]
    public string title { get; set; }

    [DataMember]
    public int DifficultyID { get; set; }
    [DataMember]
    public virtual Difficulty Difficulty { get; set; }
}

[DataContract(IsReference=true)]
public class Difficulty
{
    [DataMember]
    public int DifficultyID { get; set; }

    [DataMember]
    [Required]
    public string NameToDisplay { get; set; }
}

接下来,我创建了 WCF 服务应用程序并将其设为 RESTful。下面是接口代码:

[ServiceContract]
public interface ICosikService
{
    [OperationContract]
    [ApplyDataContractResolver]
    [WebGet(UriTemplate = "/cosik")]
    Cosik GetCosik();
}

以及该合同的实施

public class RecipeService : IRecipeService
{
//repository of Cosik entities - stores collection of all
//Cosik entities that can be queried from DB
private ICosikRepository cosikRepo;
...

public Cosik GetCosik()
    {
        Cosik c = cosikRepo.GetById(1);
        return c;
    }

我实现了在 http://msdn.microsoft.com/en-us/library/ee705457.aspx 上给出的 ApplyDataContractResolverAttribute 类,并在 GetCosik 方法中添加了 [ApplyDataContractResolver] 注释。但是,它没有帮助。

有什么我错过的建议吗?

【问题讨论】:

  • 您的服务操作 GetCosik() 中的 Cosik 看起来像您标记为数据协定的 Cosik在您的实体模型中定义并且您的服务由于某种原因试图返回。
  • 如果您在ObjectContext 中使用context.ContextOptions.LazyLoadingEnabled = false 禁用延迟加载,您是否仍然会遇到同样的错误?
  • 你能在你的 RecipeService 类上面添加 [KnownType(Cosik)] 吗?
  • 当我切换代理创建时,我没有收到错误,但检索到的 Cosik 中的难度字段为空。我可以再次查询数据库以获取正确的难度对象并自己设置难度字段。但是通过这种方式,我失去了 EF 提供的全部功能。有没有不松手的方法?我已经尝试过 [KnownType(Cosik)],但仍然遇到同样的错误。

标签: wcf serialization entity-framework-4.1 poco


【解决方案1】:

不要开发自定义解析器,而是关闭代理创建。代理不适用于 WCF 之类的场景,因为在序列化期间无论如何都必须关闭延迟加载,并且从不使用动态更改跟踪:

context.Configuration.ProxyCreationEnabled = false;

【讨论】:

  • 通过关闭代理创建,我的所有虚拟对象(字段)都变为空,并且我失去了 EF 提供的功能。我想知道这是否真的是我必须自己查询数据库以使用适当的数据设置虚拟字段的情况。我浏览了很多页面来解释如何使用 wcf 以及简单数据的简单示例,但简单数据在现实世界中相当稀少。谁能指出一些资源/教程来解释如何在更复杂的数据上使用 rest wcf 和 EF?现在我使用 wcf(不休息)并且它可以工作,但我想学习如何在休息方式中使用它
  • 您的虚拟字段为空,因为您没有使用预加载。在您知道需要数据不正确的情况下使用延迟加载,因为 EF 必须为“每个属性”创建单独的数据库往返。
  • @anetafr 要获得更好的 REST 支持,请查看项目项类型“WCF 数据服务”,它可以与代码优先一起使用,尽管它确实有自己的障碍 (blogs.msdn.com/b/writingdata_services/archive/2011/06/15/…)。就我个人而言,我会选择在我的服务层中在实体和 DTO 之间进行转换的更简洁的选项。无论如何,您可以考虑其他几个选项..
  • WCF 中从未使用过动态更改跟踪?你为什么这么认为?
  • @jannagy02:因为当实体上的属性被修改时,动态更改跟踪用于将更改通知推送到上下文。这不适用于 WCF。在客户端上完成更改后,您无法推送单个通知,并且当您收到服务调用时,所有更改都已应用于收到的实体,并且您很可能不会修改实体的另一个附加实例上的单个属性,只是为了重播所做的更改客户。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多