asp.net-mvc - 将 Entity Framework 与温莎城堡一起使用

标签 asp.net-mvc entity-framework inversion-of-control castle-windsor

我使用 Entity Framework 数据库优先方法为 MVC 应用程序生成 DbContext/POCO 模型。我想避免在我的 Controller 中依赖 DbContext 以使我能够根据需要切换到另一个持久性提供程序(例如用于单元测试目的)。

为此,我想使用 CaSTLe Windsor IoC 容器。我计划将 DbContext 注册为 IUnitOfWork 服务并注册一个通用 IRepository 服务,我将使用它的实现来访问和使用模型中的聚合根。

我是 Windsor 的新手,无法找到有关在 EF 中使用它的更多信息,我有几个问题:

  • 如果我想将 EF 与应用程序分离,这是一种合理的方法吗?
  • 如何安装/注册 IUnitOfWork 和通用 IRepository 服务?
  • 最佳答案

    所以,一些结论。我想我会写下来,以防其他人尝试一起使用/单元测试 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/

    相关文章:

    c# - MVC4 EF代码在生产中首先数据库初始化不完整

    jquery - 将数组从 Controller 传递到 Web 服务

    c# - Entity Framework Linq 查询 : runs instantly in SSMS and 8-10s in EF LINQ 出现问题

    c# - 在 Entity Framework 中将 tinyint 字段表示为枚举

    domain-driven-design - DDD 聚合和实体中的 InversionOfControl(依赖注入(inject))

    jquery - 使用 ASP MVC 和 jquery 不显眼的验证处理 textarea 元素中的换行符

    c# - 状态 cookie 无效。处理远程登录时遇到错误。 ASP.NET Core MVC 外部社交登录

    asp.net-mvc - 如何克服此错误 :- Collection was modified; enumeration operation may not execute.“

    c# - 使用 Unity 自动注册所有接口(interface)

    c# - autofac 中的工厂模式