MethodCallExpression для Count - PullRequest
1 голос
/ 04 мая 2020

Я пытаюсь подсчитать количество различных значений в свойстве типа c.

У меня Select и Distinct работает, у меня проблемы с вызовом Count.

Это правда, что я мог бы просто явно вызвать .Count(), как в примере, но мне нужно, чтобы это работало, когда я приду к другим агрегатам, таким как Sum, et c.

Кроме того, как мне получить int? Я думаю .First()?

    {
        public string S { get; set; }
    }


    class Program
    {
        private static readonly List<Thing> Things = new List<Thing>()
        {
            new Thing(){ S = "dE" },
            new Thing(){ S = null },
            new Thing(){ S = "55" },
            new Thing(){ S = "efg5" },
            new Thing(){ S = "55" }

        };

        static void Main(string[] args)
        {
            PropertyInfo pi = typeof(Thing).GetProperty(columnName);
            ParameterExpression z = Expression.Parameter(typeof(Thing), "z");
            MemberExpression me = Expression.MakeMemberAccess(z, pi);
            LambdaExpression le = Expression.Lambda(me, z);
            UnaryExpression lq = Expression.Quote(le);
            MethodCallExpression select = Expression.Call(typeof(Queryable), "Select", new Type[] { q.ElementType, pi.PropertyType }, q.Expression, lq);
            MethodCallExpression distinct = Expression.Call(typeof(Queryable), "Distinct", new Type[] { pi.PropertyType }, select);
            MethodCallExpression count = Expression.Call(typeof(Queryable), "Count", new Type[] { pi.PropertyType }, distinct);

            IQueryable<Thing> q = Things.AsQueryable();

            int i = q.Provider.CreateQuery<string>(select).Distinct().Count(); // Works
            int j = q.Provider.CreateQuery<string>(distinct).Count(); // Works

            var wtf = q.Provider.CreateQuery<int>(count); // System.ArgumentException: 'Argument expression is not valid'

           int k = wtf.First(); // This feels wrong.
        }


Edit: `IQueryable<Thing> q = Things.AsQueryable();`

1 Ответ

1 голос
/ 06 мая 2020

IQueryProvider интерфейс предоставляет два набора методов - CreateQuery и Execute .

Первый предназначен для building запросы из выражений, которые представляют IQueryable результат, например, с вашим образцом

IQueryable<string> selectQuery = q.Provider.CreateQuery<string>(select);
IQueryable<string> distinctQuery = q.Provider.CreateQuery<string>(distinct);

, тогда как последний предназначен для выполнения запросов из выражений, которые представляют немедленный результат (например, Count, Sum, Max, First et c.), Например, с вашим образцом

int countResult = q.Provider.Execute<int>(count);

На самом деле вы можете видеть это в реализации Queryable методов . При вызове все методы просто создают выражение, представляющее собой вызов, который затем передается либо CreateQuery, либо Execute в зависимости от типа возвращаемого метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...