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的例子。我只是想知道为什么我不能用这种简单的方式。
我不知道为什么它不起作用,这看起来像是可以做的事情,但实体不喜欢它,在这个链接:
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方法做同样的事情,但它确实允许我模拟实现的实际查询,并断言测试类在此基础上返回正确的结果。如果在测试的类方法中更改查询,则测试失败。