为什么DbContext没有实现IDbContext接口?

时间:2012-09-04 12:28:33

标签: entity-framework unit-testing testing mocking moq

为什么实体框架中没有IDbContext接口?如果现有的接口有类似SaveChanges()等的方法,你可以从中导出自定义数据库上下文接口吗?

public interface ICustomDbContext : IDbContext
{
    // add entity set properties to existing set of methods in IDbContext
    IDbSet<SomeEntity> SomeEntities { get; }
}

4 个答案:

答案 0 :(得分:14)

我看到了IDbContext

See this link然后为您的Entities Context With That接口创建一个新的分部类。

public partial class YourModelEntities : DbContext, IDbContext 

EDITED: 我编辑了这篇文章,这对我有用。 我的背景

namespace dao
{
    public interface ContextI : IDisposable
    {
        DbSet<TEntity> Set<TEntity>() where TEntity : class;
        DbSet Set(Type entityType);
        int SaveChanges();
        IEnumerable<DbEntityValidationResult> GetValidationErrors();
        DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity:class;
        DbEntityEntry Entry(object entity);
        string ConnectionString { get; set; }
        bool AutoDetectChangedEnabled { get; set; }
        void ExecuteSqlCommand(string p, params object[] o);
        void ExecuteSqlCommand(string p);
    }
}

YourModelEntities是您自动生成的分部类,您需要创建一个具有相同名称的新分部类,然后添加新的上下文接口,对于此示例是ContextI

注意:该接口尚未实现所有方法,因为这些方法是在自动生成代码中实现的。

namespace dao
{
    public partial class YourModelEntities :DbContext, ContextI
    {
        public string ConnectionString
        {
            get
            {
                return this.Database.Connection.ConnectionString;
            }
            set
            {
                this.Database.Connection.ConnectionString = value;
            }
        }

        bool AutoDetectChangedEnabled
        {
            get
            {
                return true;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void ExecuteSqlCommand(string p,params object[] os)
        {
            this.Database.ExecuteSqlCommand(p, os);
        }

        public void ExecuteSqlCommand(string p)
        {
            this.Database.ExecuteSqlCommand(p);
        }

        bool ContextI.AutoDetectChangedEnabled
        {
            get
            {
                return this.Configuration.AutoDetectChangesEnabled;
            }
            set
            {
                this.Configuration.AutoDetectChangesEnabled = value;
            }
        }

    }
}

答案 1 :(得分:0)

我也想到了这一点,我假设你将把它用于嘲笑 DbContext。我没有理由这样做,除非您需要手动为您的模拟类手动实现自己的DbSet(因此无论如何都需要重写您自己的界面)。

答案 2 :(得分:0)

只需创建一个模拟DbContext,扩展您的生产DbContext,覆盖使测试复杂化的方法。这样,除了重写的方法之外,对生产DbContext的任何更改都会自动反映在测试中。对于处理持久性的任何其他类,并使用DbContext只是扩展它们以及传递扩展模拟DbContext。

namespace Test.Mocks
{  
    public sealed class MockDatabaseContext : MainProject.Persistence.Database.DatabaseContext
    {
        public MockDatabaseContext(ConfigurationWrapper config) : base(config)
        {

        }      
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {

            var dbPath = "test.db";
            optionsBuilder.UseSqlite($"Filename={dbPath}");


        }
    }
}

namespace Test.Mocks
{

    public class MockInventoryFacade : InventoryFacade
    {        
        public MockInventoryFacade(MockDatabaseContext databaseContext) : base(databaseContext)
        {

        }    
    }
}

答案 3 :(得分:-11)

没有IDbContext,因为它没用,唯一的实现就是DbContext。

如果你看一下这个design meeting note

,EF团队也会用IDbSet这样做

对我来说,EF在单元测试方面的真正问题是DbContext中的DbConnection,幸运的是,{c}在C​​odeplex上有一个很好的项目开始填充它。

  

Effort是一个功能强大的工具,可以方便地为基于Entity Framework的应用程序创建自动化测试。    它基本上是一个ADO.NET提供程序,它在轻量级进程内主数据库而不是传统的外部数据库上执行所有数据操作。它提供了一些直观的帮助方法,使得这个提供程序与现有的ObjectContext或DbContext类一起使用变得非常容易。对现有代码的简单添加可能足以创建可在没有外部数据库的情况下运行的数据驱动测试。

有了这个,您可以保留DbContext和DbSet,并轻松完成单元测试。 唯一的缺点是Linq提供商之间的差异,其中一些单元测试可能会通过努力而不是真正的后端。

使用EF7更新

我仍然认为IDbContext没用,问题来自DbConnection。

EF7也没有IDbContext,为了进行单元测试,他们现在提供内存提供商。

你可以看到Rowan Miller在这里做一个演示:Effort