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

时间:2011-07-19 13:48:39

标签: c# entity-framework-4.1 repository-pattern ef-code-first wcf-data-services

我们在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数据服务(支持Code First的CTP)来访问实体。我们也希望在该服务中使用存储库。但这似乎很棘手。直接使用MyEntityContext时,服务如下所示:

public class MyEntityService : DataService<MyEntityContext>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("MyEntities", EntitySetRights.All);
    }
}

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

  1. 为通用DataService<..>指定的类型需要是一个具有默认构造函数的类,这会打破漂亮的按合同设计和依赖注入设计。
  2. 甚至看来提供的类型必须是DbContext类:我尝试使用MyEntityRepository代替,但失败了(详见详情)。
  3. 我好像迷路了...有人能把我带回正轨吗?


    详细说明:

    我的第一次去:

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

    但是,在调用服务时,它会失败,并显示以下错误消息:

      

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

    我尝试了以下步骤来解决此问题,但没有消除此错误消息:

    • 向MyEntity添加[DataServiceKey("MyEntityId")],其中 MyEntityId 是该实体的正确密钥属性。
    • Repository.MyEntities代替IDbSet替换IQueryable的类型。

    BTW:以下帖子 重复:

2 个答案:

答案 0 :(得分:3)

为什么要使用存储库?你有上下文所以使用它。不要因为想要使用模式而创建洋葱架构。 WCF数据服务已经处理了您自己需要的所有内容。不用抱歉,它有时提供更多(例如拦截器)。

通过使用自定义存储库,您将转移到reflection provider data source。如果您还计划通过同样针对您的存储库的WCF数据服务来修改您的实体,因为反射提供程序是只读的,除非它也实现了IUpdateable。另请检查rules for reflection provider

顺便说一下。 .NET 4中的WCF数据服务不直接支持DbContext(该支持仅在即将推出的版本的CTP中),但您有workaround for that。该链接适用于旧的CTP。在当前版本中,没有UnderlyingContext属性,但您可以使用IObjectContextAdapter获取ObjectContext

正如您还可以看到提供给服务的最后一个链接类型不需要具有默认构造函数 - 这取决于您在创建数据源时使用的构造函数。如果需要依赖注入,则可能必须检查如何直接注入服务本身的方式(例如Unity和普通WCF的here)并使用CreateDataSource中的注入数据。

答案 1 :(得分:1)

以下是如何使用您正在使用的任何模式制作WCF数据服务,甚至根本没有。

Getting Started With OData Part 2: Building an OData Services from Any Data Source

只需确保您的实体,poco,模型或其他具有属性public int ID的内容,或者System.Data.Services System.Data.Services namespace:程序集提供此类注释>

[DataServiceKey("TheNameOfYourPrimaryKeyProperty")]

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

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