【问题标题】:Share POCO types between WCF Data Service and Client Generated by Add Service Reference在 WCF 数据服务和添加服务引用生成的客户端之间共享 POCO 类型
【发布时间】:2012-09-21 06:48:57
【问题描述】:

我有一个 WCF 数据服务层,它公开 POCO T4 模板生成的 POCO 实体。这些 POCO 实体是在他们自己的项目(即 Company.ProjectName.Entities)中创建的,因为我想尽可能地分享它们。

我在另一个项目 (Company.ProjectName.Clients) 中有一组接口,它们通过添加对 Company.ProjectName.Entities.dll 的程序集引用来引用这些 POCO 类型。这些接口的实现之一是一个 .NET 客户端,我想使用 WCF 数据服务客户端库来使用该服务。

我已使用添加服务引用来添加服务引用。这会生成服务使用的 DataServiceContext 客户端类和 POCO 实体。但是,添加服务引用实用程序生成的这些 POCO 类型现在具有不同的命名空间(即 Company.ProjectName.Clients.Implementation.WcfDsReference)。

这意味着接口中定义的 POCO 类型不能被实用程序生成的类型使用,而无需强制转换或映射。

即假设我有:

 1. POCO Entity:     Company.ProjectName.Entities.Account
 2. Interface:       interface IRepository<Company.ProjectName.Entities.Account>{....}
 3. Implementation:  ServiceClientRepository : IRepository<Company.ProjectName.Entities.Account>
 4. WcfDsReference:  Company.ProjectName.Clients.Implementation.WcfDsReference
          &          Company.ProjectName.Clients.Implementation.WcfDsReference.Account


   Let's say I want to create a DataServiceQuery query on the Account, I won't be able to do this:

   var client = new WcfDsReference(baseUrl);
   var accounts = client.CreateQuery<Company.ProjectName.Entities.Account>(...)

      OR:         client.AddToAccounts(Company.ProjectName.Entities.Account)

   , because the CreateQuery<T>() expects T to be of type            &       Company.ProjectName.Clients.Implementation.WcfDsReference.Account

我目前要做的是将正确的实体传递给 CreateQuery 方法,并且必须将结果映射回接口可以理解的类型。 (可以使用映射器,但似乎不是一个好的解决方案。)

所以问题是,有没有办法让“添加服务引用”实用程序生成使用 Company.ProjectName.Entities 命名空间中的 POCO 类型的方法?

我正在考虑的一个解决方案是不使用该实用程序来生成 DataServiceContext 和其他类型,而是创建我自己的。

另一个解决方案是更新IRepository&lt;T&gt; 接口以使用该实用程序生成的POCO 类型。但这听起来有点老套。

有没有人提出过更好的解决方案或者有什么建议?

【问题讨论】:

  • +1 我也很想知道这个。
  • Service reference complex types 的可能重复项
  • 在您执行添加服务引用的客户端项目中,添加 Company.ProjectName.Entities.dll 作为引用。现在启动“添加服务引用”实用程序并尝试生成代理。默认情况下,“添加服务引用”将重用引用程序集中定义的类型,导致您的客户端代理代码不重新定义 POCO 类型,而是直接从 Company.ProjectName.Entities.dll 使用它们。

标签: wcf service reference poco


【解决方案1】:

好的,在开始赏金几个小时后,我发现了为什么它没有按预期工作。

事实证明,共享过程非常简单。需要做的就是用[DataServiceKey] 属性标记模型类。 This article 在“公开另一个数据模型”部分中很好地解释了该过程

考虑到这一点,我想做的是以下几点:

  1. 将模型放在单独的类库项目 C 上,并与 Web 应用程序项目 A 和 B 共享它
  2. 在项目 A 上创建数据服务
  3. 在项目 B 上添加服务引用
  4. 从服务引用中删除生成的模型代理,并更新它以使用我在项目 C 中的模型类
  5. 将 DataServiceKey 属性添加到模型,指定正确的键

当我尝试这个时它不起作用,给我以下错误:

客户端和服务之间存在类型不匹配。类型 {MyType} 不是实体类型,而是 响应负载表示实体类型。请确保类型 客户端上定义的匹配服务的数据模型,或者更新 客户端上的服务引用。

此问题是由项目 C(使用 System.Data.OData 程序集上的库存实现)和调用服务的客户端项目 B(使用 Microsoft.Data.OData 程序集)之间的版本不匹配引起的packages)。通过匹配两端的版本,它第一次工作。

在这一切之后,一个问题仍然存在:服务引用过程仍然没有检测到要共享的模型,这意味着代理正在像往常一样创建。这导致我选择退出自动服务集成机制,而是迫使我继续使用我自己的一个简单类作为 Wcf 数据服务的客户端。基本上,它是通常自动生成的类的一个经过大量修剪的版本:

using System;
using System.Data.Services.Client;
using System.Data.Services.Common;
using Model;

public class DataServiceClient : DataServiceContext
{
    private readonly Lazy<DataServiceQuery<Unit>> m_units;

    public DataServiceClient(Uri _uri)
        : base(_uri, DataServiceProtocolVersion.V3)
    {
        m_units = new Lazy<DataServiceQuery<Unit>>(() => CreateQuery<Unit>("Units"));
    }

    public DataServiceQuery<Unit> Units
    {
        get { return m_units.Value; }
    }
}

这很简单,因为我只在只读模式下使用该服务。不过,我仍然希望使用服务引用功能,这可能会避免未来的维护问题,正如在这个简单案例中硬编码的 EntitySet 名称所证明的那样。目前,我正在使用这个实现,并完全删除了服务引用。

如果有人可以分享解决方法,我真的很希望看到它与服务参考方法完全集成,但这种自定义方法对于我们当前的需求是可以接受的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 2010-12-26
    • 2016-12-04
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    相关资源
    最近更新 更多