Var против IEnumerable, когда дело доходит до Entity Framework - PullRequest
2 голосов
/ 29 сентября 2011

Если бы я использовал IEnumerable вместо var в приведенном ниже примере кода, будет ли SQL генерироваться только во время выполнения оператора foreach?Или он будет выполняться как, когда операторы Linq оцениваются?

var query = db.Customers.Where (c => c.Age > 18);
query = query.Where (c => c.State == "CO");
var result = query.Select (c => c.Name);

foreach (string name in result)   // Only now is the query executed!
   Console.WriteLine (name);

Другой пример:

IEnumerable<Order> query = db.Orders.Where(o => o.Amount > 1000);
int orderCount = query.Count();

Было бы лучше использовать var (или IQueryable) так, как он будет выполненсчетчик выбора (*) ... при выполнении .Count () или он будет точно таким же с кодом IEnumerable, показанным выше?

Ответы [ 3 ]

4 голосов
/ 29 сентября 2011

Это не имеет значения.var - это просто синтаксический сахар.Если вы наведите курсор мыши на var, вы увидите, какой тип C # считает ваш запрос.

From http://msdn.microsoft.com/en-us/library/bb383973.aspx

Начиная с Visual C # 3.0, переменные, которые объявлены в методеобласть действия может иметь неявный тип var.Локально типизированная локальная переменная строго типизирована, как если бы вы сами объявили тип, но компилятор определяет тип.Следующие два объявления i функционально эквивалентны:

var i = 10; // implicitly typed
int i = 10; //explicitly typed

Если вы хотите выполнить над запросом действия, которые SQL не будет знать, что делать, например, метод, определенныйв вашем классе вы можете использовать AsEnumerable().

Например:

var query = db.Customers
    .Where(c => c.Age > 18)
    .AsEnumerable()
    .Select(c => GetCustomerViewModel());

//put definition of GetCustomerViewModel() somewhere in the same class

Обновление

Как упоминал Омар,если вы хотите, чтобы ваш запрос был выполнен немедленно (а не отложен), используйте ToList().Это немедленно перечислит IQueryable / IEnumerable и заполнит список фактическими данными из базы данных.

2 голосов
/ 29 сентября 2011

Как правило, SQL генерируется, когда GetEnumerator вызывается в IQueryable.

В вашем примере есть небольшая разница, которую вы можете рассмотреть. Давайте возьмем ваш оригинальный пример:

var query = db.Customers.Where (c => c.Age > 18); 
query = query.Where (c => c.State == "CO"); 
var result = query.Select (c => c.Name); 

В этом случае, если вы измените свой первый запрос на IEnumerable query = ..., тогда во второй строке будет использоваться версия IEnumerable расширения Where (LINQ to Objects), а не IQueryable (LINQ to SQL / EF) , В результате, когда мы начинаем итерацию, первое предложение where передается в базу данных, а второе предложение where выполняется на стороне клиента (поскольку оно уже преобразовано в IEnumerable).

Еще один тонкий элемент, о котором вы хотите знать, - это код следующего типа:

var query = db.OrderBy(c => c.State);
query = query.Customers.Where(c => c.Age > 18); // Fails: Widening

В этом случае, поскольку ваш исходный запрос возвращает IOrderedQueryable, а не IQueryable. Если вы попытаетесь назначить запрос результату операции .Where, вы попытаетесь расширить область действия возвращаемого типа, и компилятор откажется выполнить это расширение. В результате вы должны явно указать базовый тип, а не использовать var:

IQueryable<Customer> query = db.OrderBy(c => c.State);  // Is narrowing rather than widening.
query = query.Customers.Where(c => c.Age > 18); 
2 голосов
/ 29 сентября 2011

Linq-запросы возвращают IQueryable<> или IEnumerable<>, выполнение обоих отложено.

Как указано DanM, независимо от того, используете ли вы var или IEnumerable<>, все зависит от возвращаемого значения вызываемого вами метода: если это IEnumerable<> или IQuerable<>, это будет Если вы используете .ToList(), оно будет выполнено сразу.

Когда использовать var сводится к личному выбору / стилю. Я обычно использую var, когда возвращаемое значение понимается из строки кода и имени переменной или если я создаю экземпляр универсального с длинным объявлением, например, Dictionary<string, Func<Order, object>>.

Из вашего кода ясно, что возвращается коллекция Customers / Orders, поэтому я бы использовал ключевое слово var. Опять же, это вопрос личных предпочтений.

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