我使用 Entity Framework 数据库优先方法为 MVC 应用程序生成 DbContext/POCO 模型。我想避免在我的 Controller 中依赖 DbContext 以使我能够根据需要切换到另一个持久性提供程序(例如用于单元测试目的)。
为此,我想使用 CaSTLe Windsor IoC 容器。我计划将 DbContext 注册为 IUnitOfWork 服务并注册一个通用 IRepository 服务,我将使用它的实现来访问和使用模型中的聚合根。
我是 Windsor 的新手,无法找到有关在 EF 中使用它的更多信息,我有几个问题:
最佳答案
所以,一些结论。我想我会写下来,以防其他人尝试一起使用/单元测试 EF、Windsor 和 MVC。
首先,由于 DbContext 实现了 Repository 和 Unit of Work 模式,您需要考虑这些实现是否会提供服务,或者您是否需要创建自己的实现。
我选择创建自己的存储库,遵循 DDD 模式:每个聚合根一个。原因:封装查询代码,防止泄漏到应用层,在测试应用 Controller 时更容易模拟。我创建了一个基于 IRepository<TEntity>
的通用存储库.那里有很多例子。我发现这个不错:http://architects.dzone.com/articles/implementing-repository
另一方面,我决定放弃 IUnitOfWork 服务,而选择默认实现。但是,我创建了一个 IDbContext 抽象(不知道为什么微软自己不这样做),这样我就可以在测试存储库服务时模拟 DbContext。
我只给了 IDbContext 我想在存储库中使用的 DbContext 成员。所以:
public interface IDbContext: IDisposable
{
Database Database { get; }
DbEntityEntry Entry(object entity);
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
}
然后,我为我的 IDbContext 和 IRepository 服务创建了 Windsor 工具和安装程序:
public class EntityFrameworkFacility: AbstractFacility
{
protected override void Init()
{
Kernel.Register(Component.For<IDbContext>()
.ImplementedBy<MyEntities>()
.LifestylePerWebRequest(),
Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(Repository<>))
.LifestylePerWebRequest());
}
}
public class PersistenceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<EntityFrameworkFacility>();
}
}
最后一步是扩展 Entity Framework 上下文类以实现 IDbContext,并隐藏 Set() 方法以返回 IDbSet 而不是 DbSet:
public partial class MyEntities : IDbContext
{
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
}
有了所有这些(以及 Windsor 文档中说明的 ControllerFactory 注册),让 Windsor 根据需要将 IRepository 对象(或 IDbContext)注入(inject) Controller 构造函数变得很简单:
public ControllerBase(IRepository<Contact> repo)
{
_repo = repo;
}
在存储库单元测试中,可以使用模拟 IDbContext 支持真实的存储库实例:
mocks = new MockRepository();
context = mocks.StrictMock<IDbContext>();
repo = new Repository<Contact>(context);
在 Controller 单元测试中,可以使用模拟存储库:
mocks = new MockRepository();
repo = mocks.StrictMock<IRepository<Contact>>();
ContactController controller = new ContactController(repo);
关于asp.net-mvc - 将 Entity Framework 与温莎城堡一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15654536/