EF6:从派生的DbSet获取数据

本文关键字:DbSet 获取 数据 派生 EF6 | 更新日期: 2023-09-27 18:15:59

我这样做的最终原因是为DbContext提供一些缓存功能。为了实现这一点,我试图通过在上下文中重写Set<T>()方法来扩展默认的DbSet功能,并返回直接从一般DbSet类派生的类型对象。这样的:

public class Context : DbContext
{
    ...
    public override DbSet<TEntity> Set<TEntity>()
    {
        //var set = base.Set<TEntity>();
        var set = new XxSet<TEntity>();
        return set;
    }
}
class XxSet<TEntity> : System.Data.Entity.DbSet<TEntity>
    where TEntity : class
{
    public override TEntity Find(params object[] keyValues)
    {
        return base.Find(keyValues);
    }
}

看起来清晰简单,但是当我运行测试时,EF给了我一个错误:

成员IQueryable。尚未在类型上实现提供程序继承自DbSet - 1的"XxSet - 1"。'DbSet - 1'的测试双精度必须提供所使用的方法和属性的实现。

它要求我实现IQueryable接口。我明白了,但为什么呢?它不应该已经在基类中实现了吗?我想它必须,否则,如何工作的Set<T>()方法的基本功能,这是返回由System.Data.Entity.DbSet<TEntity>类型实例化的对象。

我错过了什么吗?

顺便说一句。我知道微软创建内存中dbset的例子。我只是想知道为什么我不能用这种简单的方式。

EF6:从派生的DbSet获取数据

我不知道为什么它不起作用,这看起来像是可以做的事情,但实体不喜欢它,在这个链接:

NSubstitute DbSet/IQueryable

有类似的错误,如果没有帮助,很抱歉-

这就是答案吗?很高兴能帮到你。

我在实现继承IDbSet的接口的类时遇到了一些这样的问题。这是因为所有(或至少大部分)IQueryable方法都没有在DbSet中实现,而是Queryable类的扩展方法。大多数模拟框架不能模拟静态扩展方法。我克服了这个问题,将方法添加到我的派生接口中,并在我的类:IDerivedDbSet中实现了这些方法,如下所示:

 public IQueryable<T> Where(Expression<Func<T, bool>> predicate)
    {
        return this._dbSet.Where(predicate);
    }
    public bool Any(Expression<Func<T, bool>> predicate)
    {
        return this._dbSet.Any(predicate);
    }

测试使用这些方法的地方有点脏,因为您现在必须模拟方法,而不是依赖于实际执行由模拟注入的IQueryable扩展。下面是一个例子:

 this._context = Substitute.For<IDerivedContext>();
 this._permissionSet = Substitute.For<IDerivedSet<Permission>> ();
 this._permission1 = new Permission
        {
            UserID = 1,
            MenuID = 26,
            PermissionAllow = true
        };
 var queryable = (new List<Permission> { this._permissionLink1 }).AsQueryable();
 this._permissionSet.Any(Arg.Any<Expression<Func<Permission, bool>>>()).Returns(x => queryable.Any((Expression<Func<Permission, bool>>)x[0]));
 var result = this._permissionsProvider.HasPermissionToSomething(this._context, 1);
 Assert.IsTrue(result);

脏位是用于IDerivedDbSet的表达式参数。然后将任何方法用作Queryable的表达式参数。querable上直接调用的任何扩展方法。这不是很好,因为它假设两个Any方法做同样的事情,但它确实允许我模拟实现的实际查询,并断言测试类在此基础上返回正确的结果。如果在测试的类方法中更改查询,则测试失败。