加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 使用城堡温莎的实体框架

发布时间:2020-12-15 18:42:17 所属栏目:asp.Net 来源:网络整理
导读:我使用实体框架数据库优先方法为MVC应用程序生成DbContext / POCO模型。我想避免在控制器中依赖DbContext使我能够根据需要切换到另一个持久性提供者(例如用于单元测试)。 为此,我想使用Castle Windsor IoC容器。我计划将DbContext注册为IUnitOfWork服务,并
我使用实体框架数据库优先方法为MVC应用程序生成DbContext / POCO模型。我想避免在控制器中依赖DbContext使我能够根据需要切换到另一个持久性提供者(例如用于单元测试)。

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

我是Windsor的新人,还没有找到很多有关使用EF的信息,我有几个问题:

>如果我想从应用程序中分离EF,这是一个合理的方法吗?
>如何安装/注册IUnitOfWork和通用的IRepository服务?

解决方法

所以有一些结论。我以为我会写这个,以防其他人试图使用/单元测试EF,Windsor和MVC一起使用。

首先,由于DbContext同时实现了Repository和Work of Work模式,您需要查看这些实现是否可以提供,还是需要创建自己的。

我选择创建自己的存储库,遵循DDD模式:每个聚合根一个。原因:封装查询代码,防止漏洞进入应用层,并能够在测试应用控制器时更轻松地模拟。我创建了一个基于IRepository< TEntity>的通用存储库。那里有很多例子。我发现这是一个很好的:http://architects.dzone.com/articles/implementing-repository

另一方面,我决定删除IUnitOfWork服务,而不是选择默认实现。但是,我创建了一个IDbContext抽象(不知道为什么微软本身没有这样做),所以我可以在测试Repository服务时嘲笑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)注入到控制器构造函数中变得非常简单:根据需要:

public ControllerBase(IRepository<Contact> repo)
{
    _repo = repo;
}

在Repository单元测试中,真实的存储库实例可以使用模拟IDbContext进行备份:

mocks = new MockRepository();
context = mocks.StrictMock<IDbContext>();
repo = new Repository<Contact>(context);

在控制器单元测试中,可以使用模拟库:

mocks = new MockRepository();
repo = mocks.StrictMock<IRepository<Contact>>();
ContactController controller = new ContactController(repo);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读