【问题标题】:WCF, Entity Framework & Data ContractsWCF、实体框架和数据协定
【发布时间】:2009-07-13 20:34:35
【问题描述】:

使用 VS 2008 和 .NET 3.5 SP1:

我正在使用 WCF 允许客户端连接到使用实体框架读取和写入数据库条目的服务。默认情况下,从数据库自动生成的实体应用了 DataContract 属性。

不幸的是,许多公开的字段并不是供客户端使用的(即 - 谁正在访问哪些数据的记录等),出于安全原因,我宁愿让它们不被公开。有什么办法可以避免实体框架类以这种方式暴露?

注意:这不是How to prevent private properties in .NET entities from being exposed as public via services? 的副本。在那个问题中,用户希望选择性地显示某些字段,而我希望实体根本不作为 DataContract 公开。

提前致谢。

【问题讨论】:

  • 这可能类似于另一个没有完全回答的帖子:'wcf 和 A​​DO 实体框架',stackoverflow.com/questions/828302/wcf-and-ado-entity-framework
  • 我同意您给出的“wcf 和 A​​DO 实体框架”链接上的答案。或者您可以实现某种存储库模式。
  • @Nath - 我绝对同意“wcf 和 A​​DO 实体框架”的答案,但不幸的是它不能解决我的问题。答案中的第一点是“自动生成实体框架实体”,它将公开我希望作为 DataContracts 保密的数据。如果存储库模式也受到以这种方式生成的 EF 模型的支持,那么它也会有同样的问题 - 除非我遗漏了什么?
  • 使用您可以共享给 wcf 的类,您只会在 wcf 端公开您想要的模型中的项目,当您在存储库中执行 .Save(MyEntity) 时,您可以填充那里有你的审计记录。

标签: wcf entity-framework datacontract


【解决方案1】:

您是否知道您的实体不需要与数据库进行一对一的映射?特别是,您可以省略不相关的列,甚至整个表格。

实体模型是一个概念模型。您可以轻松地创建一组实体,以暴露给一组客户端(可能是 Web 服务)和另一组,映射到相同的数据库,这意味着不同的客户端(可能是 Web 应用程序)。

另一方面,我始终建议不要通过 Web 服务公开实体框架对象。不幸的是,微软通过用 [DataMember] 标记它们来公开依赖于实现的属性。我刚刚尝试了一个从 AdventureWorks 返回 SalesOrderHeader 的简单服务。我的客户收到了以下 EF 类型的代理版本:

  • EntityKeyMember
  • 结构对象
  • 实体对象
  • 实体键
  • 实体引用
  • 相关结束

这些不是您的客户需要知道的事情。

我更喜欢公开数据传输对象,并将属性从一个复制到另一个。显然,这最好通过反射或代码生成来完成,而不是手动完成。我过去是通过代码生成完成的(T4 模板)。

我没有尝试过的一个选项是AutoMapper

【讨论】:

  • 感谢您的回复,约翰。是的,我知道实体不需要一对一映射并且可以对概念模型的子集进行建模,但我认为这不会给我希望的结果。这是一个示例:假设我在会计系统中有一个帐户表,并且我想审计对哪些帐户执行了哪些操作。我需要公开帐户表中的字段,但我不希望我的潜在欺诈者看到我正在跟踪关于他的行为的哪些信息。在下一条评论中继续...
  • ...接上一条评论。当客户端调用一个函数时,我想创建一条记录并将其插入到我的审计表中以进行跟踪和分析。我想通过 EF 访问两者(无论它们是在同一个还是单独的实体容器中,对我来说并不重要)。不幸的是,我定义为数据模型一部分的任何内容都会作为 DataContract 公开。
  • 所以,不要公开那个数据模型。公开一个较小的数据模型——你想要公开的那个。不要将相同的模型暴露给潜在的欺诈者,就像您对审计系统所做的那样。
  • 啊……灯亮了。 ;) 问题不在于技术,而在于我的服务组合——太单一了。谢谢,约翰。
  • +1 好信息。 AutoMapper 对此非常有用。我已在各种数据映射应用程序中成功使用它。
【解决方案2】:

我们为 DataContract 对象使用单独的类。我们有一个带有一个方法的接口,ToContract(),我们所有的实体都在一个部分类文件中实现了这个接口。这是额外的工作,也是样板文件,但它似乎是获得我们需要的控制分离和粒度的最简单方法。

【讨论】:

    【解决方案3】:

    我基本上看到你可以做两件事:

    1. 要么通过手动删除这些项目的 [DataMember] 属性,从 DataContract 中删除那些不想公开的项目;在这种情况下,WCF 不会将属性序列化出来
    2. 您定义自己的 WCF DataContract 类,只包含您想要的那些成员,并且您想出一个逻辑来将您的 EF 实体转换为您的 WCF DataContract,例如使用AutoMapper 之类的东西可以消除(或至少限制)EF 和 WCF 实体之间繁琐的分配操作。

    马克

    【讨论】:

    • 谢谢,marc_s。关于上面的第 1 点,如何从数据库自动生成的那些项目中手动删除 [DataMember] 属性?每次我从数据库更新模型时,这是否需要手动返工?
    • 不幸的是,是的,恐怕没有自动方法来抑制我知道的那些 [DataMember] 属性。因此,您可以完全控制单独的 WCF 类的想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 2010-10-22
    相关资源
    最近更新 更多