То, как поддержать LINQ, задержало выполнение?

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
8
задан mckamey 20 August 2009 в 21:21
поделиться

4 ответа

  1. Вы должны быть очень осторожны с передачей IQueryables при использовании DataContext, потому что, как только контекст будет удален, вы больше не сможете выполнять этот IQueryable. Если вы не используете контекст, возможно, все в порядке, но имейте в виду.

  2. .Any () и .FirstOrDefault () не отложены. Когда вы вызываете их, они вызывают выполнение. Однако это может не сделать то, что вы думаете. Например, в LINQ to SQL, если вы выполняете .Any () для IQueryable, он в основном действует как IF EXISTS (SQL HERE).

Вы можете связать IQueryable следующим образом, если хотите:

var firstQuery = from f in context.Foos
                    where f.Bar == bar
                    select f;

var secondQuery = from f in firstQuery
                    where f.Bar == anotherBar
                    orderby f.SomeDate
                    select f;

if (secondQuery.Any())  //immediately executes IF EXISTS( second query in SQL )
{
    //causes execution on second query 
    //and allows you to enumerate through the results
    foreach (var foo in secondQuery)  
    {
        //do something
    }

    //or

    //immediately executes second query in SQL with a TOP 1 
    //or something like that
    var foo = secondQuery.FirstOrDefault(); 
}
5
ответ дан 5 December 2019 в 20:18
поделиться

Намного лучший вариант, чем кэширование объектов IQueryable, - это кэширование деревьев выражений. Все объекты IQueryable имеют свойство Expression (я полагаю), которое представляет текущее дерево выражений для этого запроса.

Позже вы можете воссоздать запрос, вызвав queryable.Provider.CreateQuery (выражение) или непосредственно на любом провайдере (в вашем случае это Linq2Sql Data Context).

Параметризация этих деревьев выражений немного сложнее, так как они используют ConstantExpressions для построения значения. Чтобы параметризовать эти запросы, вам придется перестраивать запрос каждый раз, когда вам нужны другие параметры.

2
ответ дан 5 December 2019 в 20:18
поделиться

Any () , используемый таким образом, откладывается.

var q = dc.Customers.Where(c => c.Orders.Any());

Any () , используемый таким образом, не откладывается, но по-прежнему транслируется в SQL (вся таблица клиентов не загружается в память).

bool result = dc.Customers.Any();

Если вам нужен отложенный Any (), сделайте это следующим образом:

public static class QueryableExtensions
{
  public static Func<bool> DeferredAny<T>(this IQueryable<T> source)
  {
    return () => source.Any();
  }
}

Что называется так:

Func<bool> f = dc.Customers.DeferredAny();
bool result = f();

Обратной стороной является то, что этот метод не позволяет выполнять подзапросы.

1
ответ дан 5 December 2019 в 20:18
поделиться

Создайте частичное применение вашего запроса внутри выражения

Func[Bar,IQueryable[Blah],IQueryable[Foo]] queryMaker = 
(criteria, queryable) => from foo in queryable.Foos
        where foo.Bar == criteria
        select foo;

, а затем вы можете использовать его с помощью ...

IQueryable[Blah] blah = context.Blah;
Bar someCriteria = new Bar();
IQueryable[Foo] someFoosQuery = queryMaker(blah, someCriteria);

Запрос может быть инкапсулирован в класс, если вы хотите сделать это более портативный / многоразовый.

public class FooBarQuery
{
  public Bar Criteria { get; set; }

  public IQueryable[Foo] GetQuery( IQueryable[Blah] queryable )
  {
     return from foo in queryable.Foos
        where foo.Bar == Criteria
        select foo;
  } 
}
0
ответ дан 5 December 2019 в 20:18
поделиться
Другие вопросы по тегам:

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