问题描述
我们在ASP.NET MVC 3应用程序中使用了存储库模式。这意味着,虽然我们使用EF 4.1 Code First来访问后端的数据,但所有的MVC控制器都是通过通用存储库类而不是直接通过DbContext子类实现的。简化的代码片段:
public class MyEntityContext:DbContext,IMyEntityContext
{
public IDbSet MyEntities {得到;组;
...
}
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 MyEntityService类:DataService&MyEntityContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule(MyEntities,EntitySetRights.All);
}
}
但是当我尝试替换 MyEntityContext
存储库有两个问题:
- 为通用
DataService< ..>
需要一个默认构造函数的类,它打破了美丽的按合同设计和依赖注入设计。 - 甚至似乎提供的类型必须是一个
DbContext
类:我尝试并使用了MyEntityRepository
,但是失败(见详情)
我似乎迷路了吗?有人可以带我回到正确的轨道吗?
详细信息:
我的第一步是:
public class MyEntityService:DataService&MyEntityRepository>
{
...
但是,当调用服务时,它失败并出现以下错误消息:
我尝试了以下步骤来解决这个问题,但没有摆脱这个错误信息:
- 添加一个
DataServiceKey(MyEntityId)]
到MyEntity,其中MyEntityId 是实体的正确键属性。 - 替换类型
Repository.MyEntities
byIDbSet
而不是IQueryable
li>
BTW:以下帖子是 不 / strong>重复:
- 。如果您还计划通过也位于您的存储库的WCF数据服务修改您的实体,因为反射提供程序是只读的,除非它还实现
IUpdateable
。另请参阅。
Btw。 .NET 4中的WCF数据服务不直接支持DbContext(该支持仅在即将发布的版本的CTP中),但您有。该链接适用于旧的CTP。在当前版本中,不存在
UnderlyingContext
属性,但您可以使用IObjectContextAdapter
获取ObjectContext
。
正如你也可以看到,最后一个提供给服务的链接类型不需要有默认的构造函数 - 这取决于你什么构造函数您在创建数据源时使用。如果您需要依赖注入,您可能必须检查如何直接注入到服务本身(例如 here for Unity和plain WCF),并使用注入的数据在
CreateDataSource
。We are using the repository pattern in our ASP.NET MVC 3 application. This means that, although we use EF 4.1 Code First to access the data in the backend, all MVC controllers do that via a generic repository class rather than directly over the DbContext subclass.
Simplified code snippet:
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; ... }
We use interfaces and dependency injection for every dependency. It works fine. Looks nice, doesn't it? But now for the caveat:
We also provide a WCF Data Service (CTP supporting Code First) to access the entities. We want to use the repository in that service, too. But this seems tricky. When using the
MyEntityContext
directly, the service looks like this:public class MyEntityService : DataService<MyEntityContext> { public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("MyEntities", EntitySetRights.All); } }
But when I try to replace the
MyEntityContext
by the repository, there are two issues:- The type specified for the generic
DataService<..>
needs to be a class with a default constructor, which breaks the pretty design-by-contract and dependency injection design. - It even seems that the type provided has to be a
DbContext
class: I tried and used theMyEntityRepository
instead, but failed (see details).
I seem lost... Can anyone bring me back on the proper track?
Details:
My first go was:
public class MyEntityService : DataService<MyEntityRepository> { ...
However, when calling the service, it fails with the following error message:
I tried the following steps to fix this, but did not get rid of this error message:
- Adding a
[DataServiceKey("MyEntityId")]
to MyEntity, where MyEntityId is the correct key property of the entity. - Replacing the type of
Repository.MyEntities
byIDbSet
instead ofIQueryable
.
BTW: The following posts are not duplicates:
- WCF Repository Service pattern with entity framework
- Service Layer/Repository Pattern
- Best way to implement Repository Pattern?
- webservices with repository pattern in c# and WCF?
- WCF Service design pattern
解决方案Why do you want to use repository? You have context so use it. Don't create onion architecture just because you want to use pattern. WCF data service already handles everything you need itself. No sorry, it sometimes offers even more (for example interceptors).
By using custom repository you are moving to reflection provider data source. If you also plan to modify your entities through WCF data service that is also against your repository because reflection provider is read only unless it also implements
IUpdateable
. Check also rules for reflection provider.Btw. WCF Data Services in .NET 4 doesn't support DbContext directly (that support is only in CTPs of upcoming version) but you there is workaround for that. The link is for old CTP. In current version there is not
UnderlyingContext
property but you can useIObjectContextAdapter
to getObjectContext
.As you can also see in last link type provided to the service doesn't need to have default constructor - it is up to you what constructor you use when creating data source. If you need dependency injection you will probably have to check the way how to inject directly to the service itself (for example here for Unity and plain WCF) and use injected data in
CreateDataSource
.这篇关于使用资源库模式实现WCF数据服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- The type specified for the generic