在WCF数据服务和通过添加服务引用生成的客户端之间共享POCO类型



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

我在另一个项目(Company.ProjectName.Clients)中有一组接口,它们通过向公司添加程序集引用来引用这些POCO类型。项目名称。Entities.dll。这些接口的实现之一是。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方法,并将结果映射回接口所理解的类型。(可以使用映射器,但似乎不是一个好的解决方案。)

因此,问题是,是否有一种方法可以让Add Service Reference实用程序生成使用公司中POCO类型的方法。项目名称。实体命名空间?

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

另一种解决方案是更新IRepository<T>接口以使用该实用程序生成的POCO类型。但这听起来有点古怪。

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

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

事实证明,共享过程相当简单。所需要做的就是用[DataServiceKey]属性标记模型类。本文在的"暴露另一个数据模型"部分很好地解释了这个过程

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

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

当我尝试此操作时,它不起作用,给了我以下错误:

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

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

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

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名称就证明了这一点。目前,我正在使用这个实现,并且已经完全删除了服务引用。

如果有人可以共享解决方法的话,我真的希望看到这种方法与服务参考方法完全集成,但这种自定义方法可以满足我们当前的需求。

相关内容

最新更新