Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEnumerable<dynamic> with linq

Tags:

c#

dynamic

linq

I am trying to build dynamic data context, linq is not support dynamic type I found this solution on

http://jrwren.wrenfam.com/blog/2010/03/04/linq-abuse-with-the-c-4-dynamic-type/

public static class ObjectExtensionMethod
{
    public static IEnumerable<dynamic> Select(this object source, Func<dynamic, dynamic> map)
    {
        foreach (dynamic item in source as dynamic)
        {
            yield return map(item);
        }
    }

    public static IEnumerable<dynamic> Where(this object source, Func<dynamic, dynamic> predicate)
    {
        foreach (dynamic item in source as dynamic)
        {
            if (predicate(item))
                yield return item;
        }
    }
}

the problem with this solution is getting all data from database after that applying the where statement. is there any way to apply where statement before getting the data from database with dynamic type

like image 886
Bakri Avatar asked Jun 15 '15 05:06

Bakri


1 Answers

the problem with this solution is getting all data from database after that applying the where statement.

The problem here is not with dynamic, but with the way you are iterating over the source. You are using foreach, and expect it to be translated to an SQL or sort of, but that is just wrong assumption. As soon as iterator is created by GetEnumerator() method call the query will be "materialized", even if real type of the source is implementing IQueryable<T>, end everything else will be performed in memory.

If you want the conditions to be translated to an SQL you need to implement IQueryableProvider.

Or, at least you can try to call underlying IQueryableProvider. But I'm not sure if it would work.

public static class ObjectExtensionMethod
{
    public static IQueryable Select<T>(this IQueryable source, Expression<Func<dynamic, dynamic>> map)
    {
        var method = new Func<IQueryable<dynamic>, Expression<Func<dynamic, dynamic>>, IQueryable<dynamic>>(Queryable.Select).Method;

        var call = Expression.Call(null, method, source.Expression, Expression.Quote(map));

        return source.Provider.CreateQuery(call);
    }

    public static IQueryable Where(this IQueryable source, Expression<Func<dynamic, bool>> predicate)
    {
        var method = new Func<IQueryable<dynamic>, Expression<Func<dynamic, bool>>, IQueryable<dynamic>>(Queryable.Where).Method;

        var call = Expression.Call(null, method, source.Expression, Expression.Quote(predicate));

        return source.Provider.CreateQuery(call);
    }
}

Please note that type of source parameter has changed from object to IQueryable and types of map and predicate parameters have changed to Expression<Func<,>>.

like image 72
hazzik Avatar answered Oct 12 '22 01:10

hazzik