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:
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.
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.
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.
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.
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.
Try using base.AsQueryable()
instead of this.AsQueryable()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With