【问题标题】:List<T> to implement IQueryable<T>List<T> 实现 IQueryable<T>
【发布时间】:2011-10-09 13:41:33
【问题描述】:

我正在尝试为我的IRepository 接口创建一个模拟:

public interface IRepository<T> : ICollection<T>, IQueryable<T>
{
}

有了这个实现:

public class RepositoryFake<T> : List<T>, IRepository<T>
{
    public Expression Expression
    {
        get
        {
            return this.AsQueryable().Expression;
        }
    }

    public Type ElementType
    {
        get
        {
            return this.AsQueryable().ElementType;
        }
    }

    public IQueryProvider Provider
    {
        get
        {
            return this.AsQueryable().Provider;
        }
    }
}

但是当我使用它时,我得到了StackOverflow 异常。如何正确实现这个接口才能只使用List 作为存储库?

使用很简单

[Test]
public void Test()
{
    RepositoryFake<User> users = new RepositoryFake<User>();
    users.Add(new User());

    List<User> list = (from user in users 
                 where user.Id == "5"
                 select user).ToList();

    Assert.That(list, Is.Empty);
}

这里是异常截图:

【问题讨论】:

  • “但是当我使用它时”——给我们看代码?向我们展示堆栈跟踪?
  • 你想做什么?我最好的猜测是你希望得到一些魔法。该行为完全符合预期。

标签: c# .net linq iqueryable


【解决方案1】:

问题的原因是,如果您执行AsQueryable,它会检查对象是否已经实现IQueryable,如果是则返回它。

使用new EnumerableQuery&lt;T&gt;(this) 代替不执行此检查的AsQueryable


.net 3.5 的解决方法:

return ((IEnumerable<T>)this).Select(x=>x).AsQueryable()

首先转换为IEnumerable&lt;T&gt;,因此选择的Select 方法将是Enumerable.Select 而不是Queryable.Select。然后身份选择将返回一个未实现IQueryable&lt;T&gt; 的新对象,因此检查它是否在AsQueryable 中实现失败。

【讨论】:

  • 采用IEnumerable&lt;T&gt; 的构造函数是公开的。检查msdn.microsoft.com/en-us/library/cc190806.aspx至少在.net 4上
  • 你将IEnumerable&lt;T&gt;Select 的演员都包括在内?
  • 第二个选项完成了这项工作。谢谢!
  • 对我来说似乎很奇怪。在我的特殊情况下,这导致我们的服务器使用 100% CPU,调试显示所有 db 行都被实例化为内存中的对象
  • @dksh 这旨在在IEnumerable 上重用IQueryable 代码,例如用于测试。它不是为查询 SQL 数据库而设计的,因为任何基于 IEnumerable 的内容,即使转换为 IQueryable 也需要遍历所有内容,而不是将查询转换为 SQL。
【解决方案2】:

尝试使用base.AsQueryable() 而不是this.AsQueryable()

【讨论】:

  • 基类没有这样的扩展
  • 无论如何都无济于事,因为检查 IQueryable&lt;T&gt; 是否已经实现使用运行时类型。这不是虚方法。
猜你喜欢
  • 2019-11-21
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
相关资源
最近更新 更多