Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<T> to implement IQueryable<T>

I'm trying to create a mock for my IRepository interface:

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

With this implementation:

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;         }     } } 

But when I use it, I'm getting StackOverflow exception. How to implement this interface correctly to be able to use just a List as a repository?

Usage is very simple

[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); } 

Here is screenshot of exception:

Exception

like image 248
Sly Avatar asked Jul 20 '11 16:07

Sly


People also ask

What implements IQueryable?

NET Framework implements IQueryable. IQueryable is an interface designed to be used to create Queryable providers, which allow the LINQ library to be leveraged against an external data store by building a parse-able expression tree.

When to use IQueryable in c#?

IQueryable is suitable for querying data from out-memory (like remote database, service) collections. While querying data from a database, IQueryable executes a "select query" on server-side with all filters. IQueryable is beneficial for LINQ to SQL queries.

How do I add data to IQueryable?

The simple answer is that unless you add the record to the underlying datastore that the Iqueryable is querying, you can't add a new record into an IQueryable. So if you are using LinqToSql then you would have to add a row into the table that the IQueryable was querying in order to "add" a row into the IQueryable.

How does IQueryable work?

The IQueryable interface inherits the IEnumerable interface so that if it represents a query, the results of that query can be enumerated. Enumeration causes the expression tree associated with an IQueryable object to be executed. The definition of "executing an expression tree" is specific to a query provider.


2 Answers

The reason for your problem is that if you perform AsQueryable it checks if the object already implements IQueryable and if yes returns it.

Use new EnumerableQuery<T>(this) instead of AsQueryable which doesn't perform this check.


Workaround for .net 3.5:

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

First casts to IEnumerable<T> so the chosen Select method will be Enumerable.Select not Queryable.Select. The identity select will then return a new object that does not implement IQueryable<T>, so the check if it's implemented in AsQueryable fails.

like image 66
CodesInChaos Avatar answered Sep 20 '22 17:09

CodesInChaos


Try using base.AsQueryable() instead of this.AsQueryable().

like image 28
Daniel A. White Avatar answered Sep 19 '22 17:09

Daniel A. White