Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum List of IQueryable

Tags:

linq-to-sql

Given a list IQueryables, how can you sum the count of each, without having multiple statements executed in the database?

 return queries
               .Sum(qy=> qy.Count());

The above works, but hits the database for each query.

like image 374
jmoreno Avatar asked Mar 23 '16 15:03

jmoreno


People also ask

How do I add an IQueryable to a list?

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.

What inherits from 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.

How do I combine two Iqueryables?

How to merge two IQueryable lists in LINQ? By using Concat() Or Union()var filter1 = from p in db. table1 var filter2 = from p in db. table2var filter3 = filter1.

Is IQueryable a collection?

Both IEnumerable and IQueryable are forward collection. Querying data from a database, IEnumerable execute a select query on the server side, load data in-memory on a client-side and then filter data. Querying data from a database, IQueryable execute the select query on the server side with all filters.


2 Answers

You can first use the Aggregate function with Concat to combine the IQueryable's and then Count the total like this:

 return queries.Aggregate((x,y) => x.Concat(y)).Count()
like image 61
Aducci Avatar answered Oct 16 '22 14:10

Aducci


Starting from this idea Sum(q1,q2) = q1.Concat(q2).Count() I've tested the following extensions:

public static class LinqExtensions
{
    public static IQueryable<object> ConcatAny<T,R>(this IQueryable<T> q1, IQueryable<R> q2)
    {
        return q1.Select(c=>(object)null).Concat(q2.Select(c=>(object)null));
    }

    public static IQueryable<object> ConcatAll(this IEnumerable<IQueryable<object>> queries)
    {
        var resultQuery = queries.First();
        foreach (var query in queries.Skip(1))
        {
            resultQuery = resultQuery.ConcatAny(query);
        }
        return resultQuery;
    }
}

I assumed you have heterogeneous queries like IQueryable<T>, IQueryable<R> so on and you are interested in counting all rows no matter which the source is.

So you might use these extensions like

var q1 = Table1.AsQueryable();
var q2 = Table2.AsQueryable();
var q3 = Table3.AsQueryable();

var queries = new IQueryable<object>[] {q1,q2,q3}; // we use here the covariance feature

return queries.ConcatAll().Count();

The generated SQL might look like this

SELECT COUNT(*) AS [value]
FROM (
    SELECT NULL AS [EMPTY]
    FROM (
        SELECT NULL AS [EMPTY]
        FROM [Table1] AS [t0]
        UNION ALL
        SELECT NULL AS [EMPTY]
        FROM [Table2] AS [t1]
        ) AS [t2]
    UNION ALL
    SELECT NULL AS [EMPTY]
    FROM [Table3] AS [t3]
    ) AS [t4]

I don't think is very effective though

like image 31
Adrian Iftode Avatar answered Oct 16 '22 12:10

Adrian Iftode