【问题标题】:How Can I Extend A Entity When Using RIA Services With Silverlight?将 RIA 服务与 Silverlight 一起使用时如何扩展实体?
【发布时间】:2011-07-19 18:48:16
【问题描述】:

在我的 Silverlight 解决方案的服务器端,我有 2 个项目。

  1. 提供 Silverlight 页面的网站。
  2. 实体框架数据访问层。

我有一个带有 FirstName 和 LastName 属性的实体。我想添加一个可从 Silverlight 客户端获得的 FullName 属性。

我已经添加了属性:

namespace Server.DAL.Model
{
    public partial class Contact
    {
        public string FullName
        {
            get
            {
                return string.Format("{0} {1}", this.FirstName, this.LastName);
            }
        }
    }
}

从服务器端测试时,这个新属性存在并且工作正常。 Silverlight 客户端上不存在该属性。我尝试使用Include 属性添加元数据类,但由于字符串是原始类型,因此在编译时出现以下错误:

实体类型“联系人”中的属性“全名”不能标记为 IncludeAttribute 因为“字符串”不是有效的实体类型。 实体类型不能是原始类型或字符串等简单类型 或指导。

如何使 Silverlight 客户端可以使用此属性?

【问题讨论】:

  • 在服务器端的 xxDataService.cs 文件中,在处理联系人的方法之一中,如果您引用 FullName 属性,您的代码是否编译?在客户端,如果查看 Generated_Code 文件夹中的 *.Web.g.cs 文件,是否可以找到 Contact 类并查看 FullName 属性是否存在?
  • @hatchet - 不,FullName 属性不存在于处理联系人实体的方法中。只有 1 个名为 EntityKeyPropertyName 的属性和 3 个方法。 *.Web.g.cs 文件为空。
  • 您是否将 [DataMember] 添加到您的 FullName 属性中?以下是向 ComplexTypes 添加方法/属性的一些说明。它们也可能适用于实体。也许使用伙伴类,我还没有为实体尝试过这个。 thegrayzone.co.uk/blog/tag/wcf-ria-services
  • @Derek Beattie - 我添加了 [DataMember] 属性并且它有效。您应该将此评论作为答案。

标签: silverlight entity-framework-4 wcf-ria-services


【解决方案1】:

将 [DataMember] 添加到您的 FullName 属性。 Here 是一些关于向 ComplexTypes 添加方法/属性的说明。它们也可能适用于实体。也许使用伙伴类,我还没有为实体尝试过这个。

namespace Server.DAL.Model
{
    public partial class Contact
    {
        [DataMember]
        public string FullName
        {
            get
            {
                return string.Format("{0} {1}", this.FirstName, this.LastName);
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    您应该将您共享的代码放入名为Contact.shared.cs 的文件中。 WCF RIA 工具完全采用此代码,并使用该代码在 Silverlight 项目中创建一个文件。然后,客户端代码可以访问此成员以及在服务器项目中编译的代码的副本。

    这里有更多关于shared code in the MSDN docs的信息。

    【讨论】:

    • 此解决方案不需要“手动”复制任何代码,这是一大优势。
    【解决方案3】:

    我假设您正在使用 RIA 服务?如果是这样,问题在于 RIA 服务只会将您的服务器端类的结构复制到客户端,而不是您在属性或方法中编写的任何自定义代码。

    好消息是,解决方案很简单,您就快到了。 RIA 服务将客户端类生成为部分类,就像 Entity Framework 在服务器上所做的那样。这意味着您可以使用分部类在 Silverlight 项目中扩展这些类,就像您在服务器项目中所做的那样。

    只需将您的类从服务器项目移动到 Silverlight 项目,确保您的命名空间与为您生成的 RIA 服务类的命名空间相匹配,您就可以开始了。

    祝你好运!

    【讨论】:

    • 在他的情况下,RIA 服务不需要将 FullName 的逻辑传递给客户端。如果它将其公开为公共属性,并在服务器上执行逻辑,则计算值应传输到客户端,并在那里可用,只要客户端模型也公开该值。也就是说,我通常按照您的建议将其作为客户端部分类来执行。
    • 有趣。我不能说我曾经尝试过在服务器上扩展类以便将计算值传播到客户端。如果您正在为多个客户端开发单个服务,这可能是有利的,因为您不会为每个客户端重新定义 FullName。但我也喜欢客户端方法,因为 a) 它总是对我有用,b) 我认为 Silverlight 项目是表示层,在我看来,计算像 FullName 这样的东西是一个表示问题!跨度>
    • @Michael Ames - 我愿意接受客户端解决方案。我正在使用 MVVM 模式。你能发布一些示例代码吗?
    • 我可以,但也许我的解释不清楚,因为除了您已经编写的代码之外,我真的没有什么可以向您展示的了。您有一个完全正确的想法,使用部分类来扩展 Contact。您需要做的唯一不同的事情是扩展 RIA 服务为您生成的联系人版本,它存在于 Silverlight 项目中,而不是扩展实体框架为您生成的版本,它存在于您的服务器项目中。跨度>
    • 您将通过将已经编写的部分类定义从服务器项目移动到 Silverlight 项目来完成此操作。拖放,宝贝!唯一需要注意的是,RIA 可能在与您定义它的名称空间不同的名称空间中生成了 Contact 类的客户端版本。在这种情况下,您需要更改名称空间定义以匹配。
    【解决方案4】:

    恕我直言,我认为将属性添加到数据模型并不是最好的方法,因为我喜欢保持模型干净(而不是特定于实现,因此我的实体可以跨各种项目工作,而不会受到其他项目的干扰)。我解决这个问题的方法是使用扩展方法。这是使用扩展方法而不是将其添加到数据成员的完全相同的场景(来自我的代码)。

    namespace <MyAppName>.Services.Entities
    {
      public static class UserExtension
      {
    
        public static String FullName(this User user)
        {
            return String.Format("{0} {1}", user.First, user.Last);
    
        }
      }
    }
    

    注意方法的参数及其定义(即这不是正常方法定义)。我有一个 "Common.dll" 包含我的应用程序的基本例程,它总是被引用......所以我将扩展方法放在那个 DLL 中。我还确保扩展方法的命名空间完全匹配实体的命名空间。如果您这样做,该方法将出现在实体上,就好像它是实体的一部分一样。

    唯一的缺点是您必须将其实现为方法,并且不能将其定义为属性....这意味着没有直接的数据绑定。但是您的 ViewModel 或 IValueConverter 可以轻松处理这个问题。

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2011-02-05
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      相关资源
      最近更新 更多