使用存储库模式实现WCF数据服务

本文关键字:WCF 数据 服务 实现 模式 存储 | 更新日期: 2023-09-27 18:03:00

我们在ASP中使用存储库模式。asp.net MVC 3应用程序。这意味着,尽管我们使用EF 4.1 Code First来访问后端数据,但所有MVC控制器都是通过一个通用的存储库类来实现的,而不是直接通过DbContext子类。

简化代码片段:

public class MyEntityContext : DbContext, IMyEntityContext
{
    public IDbSet MyEntities { get; set; }
    ...
}
public class MyEntityRepository : IMyEntityRepository
{
    private IMyEntityContext _context;
    public IQueryable<MyEntity> MyEntities
    {
        return _context.MyEntities;
    }
    ...
}
public class MyEntityController : Controller
{
    private MyEntityRepository _repository;
    ...
}

我们对每个依赖都使用接口和依赖注入。它工作得很好。看起来不错,不是吗?但是现在需要注意的是:

我们还提供了一个WCF数据服务(CTP支持代码优先)来访问实体。我们还希望在该服务中使用存储库。但这似乎很棘手。当直接使用MyEntityContext时,服务看起来像这样:
public class MyEntityService : DataService<MyEntityContext>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("MyEntities", EntitySetRights.All);
    }
}

但是当我尝试用存储库替换MyEntityContext时,有两个问题:

  1. 为泛型DataService<..>指定的类型需要是一个带有默认构造函数的类,这打破了漂亮的契约式设计和依赖注入设计。它甚至似乎提供的类型必须是DbContext类:我尝试并使用MyEntityRepository代替,但失败了(见详细信息)。

我似乎迷路了…谁能把我带回到正确的轨道上来?


细节:

我的第一次尝试是:

public class MyEntityService : DataService<MyEntityRepository>
{
    ...

然而,当调用该服务时,它失败并显示以下错误消息:

服务器在处理请求时遇到错误。异常消息是'在数据上下文类型'MyEntityRepository'上,有一个top iquerable属性'MyEntities',其元素类型不是实体类型。请确保IQueryable属性是实体类型,或者在数据上下文类型上指定IgnoreProperties属性以忽略该属性。

我尝试了以下步骤来解决这个问题,但没有摆脱这个错误消息:

  • 添加[DataServiceKey("MyEntityId")]到MyEntity,其中MyEntityId是实体的正确关键属性。
  • Repository.MyEntities的类型替换为IDbSet而不是IQueryable

BTW:以下帖子重复:

  • 带有实体框架的WCF存储库服务模式
  • 服务层/存储库模式
  • 实现仓库模式的最佳方式?
  • web服务与存储库模式在c#和WCF?
  • WCF服务设计模式

使用存储库模式实现WCF数据服务

为什么要使用repository?你有上下文,所以使用它。不要仅仅因为想要使用模式就创建洋葱架构。WCF数据服务本身已经处理了您需要的一切。不,抱歉,它有时甚至提供更多(例如拦截器)。

通过使用自定义存储库,您将移动到反射提供程序数据源。如果您还计划通过WCF数据服务修改您的实体,这也是针对您的存储库的,因为反射提供程序是只读的,除非它也实现了IUpdateable。请检查反射提供程序的规则。

顺便说一句。. net 4中的WCF数据服务不直接支持DbContext(这种支持只在即将到来的版本的ctp中),但是你有一个解决方案。此链接用于旧CTP。在当前版本中,没有UnderlyingContext属性,但您可以使用IObjectContextAdapter来获得ObjectContext

正如你在最后一个链接类型中看到的那样,提供给服务的链接类型不需要有默认构造函数——这取决于你在创建数据源时使用什么构造函数。如果你需要依赖注入,你可能需要检查如何直接注入到服务本身(例如这里的Unity和普通WCF),并在CreateDataSource中使用注入的数据。

下面是如何使用任何模式创建WCF数据服务,甚至什么模式都没有。

OData入门第2部分:从任意数据源构建OData服务

只要确保你的实体,poco,模型或任何东西有一个公共int ID属性,或者在System.Data.Services namespace:

中有System.Data.Services程序集提供的这个类注释
[DataServiceKey("TheNameOfYourPrimaryKeyProperty")]

这将使它被WCF数据服务识别为实体类型。

正如其他人指出的那样,只要确保在堆栈中添加另一层是一个好的决定。