Выражение LINQ для возврата Значения свойства?

db.collection.find({"createdDate":{$gte:new ISODate("2017-04-14T23:59:59Z"),$lte:new ISODate("2017-04-15T23:59:59Z")}}).count();

Замените collection именем коллекции, которую хотите выполнить запрос

23
задан kwcto 20 February 2009 в 14:35
поделиться

3 ответа

Самый легкий способ сделать это: Используйте LINQKit (Бесплатная, не ограничивающая лицензия)

Рабочая версия кода:

public static IEnumerable<T> SelectByParameterList<T, PropertyType>(this Table<T> items, IEnumerable<PropertyType> parameterList, Expression<Func<T, PropertyType>> propertySelector, int blockSize) where T : class
{
    var groups = parameterList
        .Select((Parameter, index) =>
            new
            {
                GroupID = index / blockSize, //# of parameters per request
                Parameter
            }
        )
        .GroupBy(x => x.GroupID)
        .AsEnumerable();

    var selector = LinqKit.Linq.Expr(propertySelector);

    var results = groups
    .Select(g => new { Group = g, Parameters = g.Select(x => x.Parameter) } )
    .SelectMany(g => 
        /* AsExpandable() extension method requires LinqKit DLL */
        items.AsExpandable().Where(item => g.Parameters.Contains(selector.Invoke(item)))
    );

    return results;
}

использование В качестве примера:

    Guid[] local_refill_ids = Refills.Select(r => r.Id).Take(20).ToArray();

    IEnumerable<Refill> results = Refills.SelectByParameterList(local_refill_ids, r => r.Id, 10); //runs 2 SQL queries with 10 parameters each

Еще раз спасибо за всю Вашу справку!

8
ответ дан kwcto 29 November 2019 в 01:25
поделиться

Я придумал способ разделить запрос на блоки в части - т.е. Вы даете ему 4 000 значений, таким образом, он мог бы сделать 4 запроса 1 000 каждый; с полным примером Northwind. Обратите внимание, что это не могло бы работать над Платформой Объекта, из-за Expression.Invoke - но прекрасно на LINQ к SQL:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApplication5 {
    /// SAMPLE USAGE
    class Program {
        static void Main(string[] args) {
            // get some ids to play with...
            string[] ids;
            using(var ctx = new DataClasses1DataContext()) {
                ids = ctx.Customers.Select(x => x.CustomerID)
                    .Take(100).ToArray();
            }

            // now do our fun select - using a deliberately small
            // batch size to prove it...
            using (var ctx = new DataClasses1DataContext()) {
                ctx.Log = Console.Out;
                foreach(var cust in ctx.Customers
                        .InRange(x => x.CustomerID, 5, ids)) {
                    Console.WriteLine(cust.CompanyName);
                }
            }
        }
    }

    /// THIS IS THE INTERESTING BIT
    public static class QueryableChunked {
        public static IEnumerable<T> InRange<T, TValue>(
                this IQueryable<T> source,
                Expression<Func<T, TValue>> selector,
                int blockSize,
                IEnumerable<TValue> values) {
            MethodInfo method = null;
            foreach(MethodInfo tmp in typeof(Enumerable).GetMethods(
                    BindingFlags.Public | BindingFlags.Static)) {
                if(tmp.Name == "Contains" && tmp.IsGenericMethodDefinition
                        && tmp.GetParameters().Length == 2) {
                    method = tmp.MakeGenericMethod(typeof (TValue));
                    break;
                }
            }
            if(method==null) throw new InvalidOperationException(
                "Unable to locate Contains");
            foreach(TValue[] block in values.GetBlocks(blockSize)) {
                var row = Expression.Parameter(typeof (T), "row");
                var member = Expression.Invoke(selector, row);
                var keys = Expression.Constant(block, typeof (TValue[]));
                var predicate = Expression.Call(method, keys, member);
                var lambda = Expression.Lambda<Func<T,bool>>(
                      predicate, row);
                foreach(T record in source.Where(lambda)) {
                    yield return record;
                }
            }
        }
        public static IEnumerable<T[]> GetBlocks<T>(
                this IEnumerable<T> source, int blockSize) {
            List<T> list = new List<T>(blockSize);
            foreach(T item in source) {
                list.Add(item);
                if(list.Count == blockSize) {
                    yield return list.ToArray();
                    list.Clear();
                }
            }
            if(list.Count > 0) {
                yield return list.ToArray();
            }
        }
    }
}
43
ответ дан Marc Gravell 29 November 2019 в 01:25
поделиться

LINQ-SQL все еще работает через стандартные параметры SQL, так запись, что необычное выражение не собирается помогать. Здесь существует 3 общих опции:

  • упаковывают идентификаторы в (например), csv/tsv; передайте как varchar(max) и используйте udf для разделения его (в сервере) в табличную переменную; соедините с табличной переменной
  • , используют табличный параметр в SQL Server, 2008
  • имеет таблицу на сервере, что Вы могли продвинуть идентификаторы в (возможно, через SqlBulkCopy) (возможно, с "гуидом сессии" или подобный); соедините с этой таблицей

, первое является самым простым; получение "разделения csv udf" тривиально (просто ищут его). Перетащите udf на контекст данных и используйте оттуда.

3
ответ дан Marc Gravell 29 November 2019 в 01:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: