使用存储库模式实现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
,有两个问题:
- 为通用
DataService
指定的类型需要是一个具有默认构造函数的类,这打破了漂亮的按合同设计和dependency injection设计。 - 甚至看起来所提供的类型必须是
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数据服务识别为实体类型。
正如其他人指出的那样,只需确保在堆栈中添加另一层是一个很好的决定。