JetBrains Rider 2023.3 Help

Code Inspection: IQueryable is possibly unintentionally used as IEnumerable

Objects that implement the IQueryable interface are meant to be processed by LINQ providers (normally, remote databases) with their specific implementations of this interface.

However, as IQueryable is inherited from IEnumerable, there could be cases when an IQueryable object is passed and processed as an IEnumerable object, meaning that all processing is done on the local machine. Such implicit conversions are not a problem in test environments, but could make a huge performance impact in production.

Suppose that you get an IQueryable object from a database:

IQueryable<Resource> resources = myDb.GetResources();

... and somewhere in your codebase there is a handy extension method for filtering out null items:

public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> items) { return items.Where(x => x != null); }

Now, let's see how we can use our queryable object:

// 'Where' will be processed in the database server and we just get the result: var notNullResources1 = resources.Where(x => x != null); // We will first get all Resource objects from the database // and then process them locally. // Also, 'notNullResources2' will be of the 'IEnumerable' type, // so all other processing of this object will be done locally as well. var notNullResources2 = resources.WhereNotNull();

JetBrains Rider will detect such a conversion and suggest a fix to make it explicit:

var notNullResources2 = resources.AsEnumerable().WhereNotNull();

Another example is method groups or expression trees, which should not be passed as 'Expression' objects in this case, and therefore trigger the same inspection. The same implicit conversion to IEnumerable happens here and JetBrains Rider suggests adding the explicit .AsEnumerable() to the call:

public static Func<object, bool> NotNullCondition => (x) => x != null; public static void Test(IQueryable<object> resources) { if (resources != null) { var notNullResources = resources.Select(NotNullCondition); } }
public static Func<object, bool> NotNullCondition => (x) => x != null; public static void Test(IQueryable<object> resources) { if (resources != null) { var notNullResources = resources.AsEnumerable().Select(NotNullCondition); } }
Last modified: 21 March 2024