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

我们在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 MyEntities { return _context.MyEntities; } ... } public class MyEntityController : Controller { private MyEntityRepository _repository; ... } 

我们为每个依赖项使用接口和dependency injection。 它工作正常。 看起来不错,不是吗? 但现在需要注意的是:

我们还提供WCF数据服务(支持Code First的CTP)来访问实体。 我们也希望在该服务中使用存储库。 但这似乎很棘手。 直接使用MyEntityContext ,服务如下所示:

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

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

  1. 为通用DataService指定的类型需要是一个具有默认构造函数的类,这打破了漂亮的按合同设计和dependency injection设计。
  2. 甚至看起来所提供的类型必须是DbContext类:我尝试使用MyEntityRepository ,但失败了(详见)。

我好像迷路了……有人能把我带回正轨吗?


细节:

我的第一次去:

 public class MyEntityService : DataService { ... 

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

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

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

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

顺便说一句:以下post重复:

  • 具有entity framework的WCF存储库服务模式
  • 服务层/存储库模式
  • 实现存储库模式的最佳方式?
  • 在c#和WCF中使用存储库模式的webservices?
  • WCF服务设计模式

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

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

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

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

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

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

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

 [DataServiceKey("TheNameOfYourPrimaryKeyProperty")] 

这将使其可由WCF数据服务识别为实体类型。

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