Entity включает, когда вложенный список [duplicate]

tl; dr: Нет! Функции стрелок и декларации функций / выражения не являются эквивалентными и не могут быть заменены вслепую. Если функция, которую вы хотите заменить, not использует this, arguments и не вызывается с new, тогда да.


Как это часто бывает: это зависит. Функции Arrow имеют другое поведение, чем декларации / выражения функций, поэтому давайте сначала рассмотрим различия:

1. Функции Lexical this и arguments

не имеют собственных привязок this или arguments. Вместо этого эти идентификаторы разрешаются в лексической области, как и любая другая переменная. Это означает, что внутри функции стрелки this и arguments относятся к значениям this и arguments в окружающей среде, функция стрелки определена в (т.е. «снаружи» стрелка )

В случае выражения функции, this относится к объекту, который был создан внутри createObject. В функциональном случае стрелки this относится к this самого createObject.

Это делает функции стрелок полезными, если вам нужно получить доступ к this текущей среды:

// currently common pattern
var that = this;
getData(function(data) {
  that.data = data;
});

// better alternative with arrow functions
getData(data => {
  this.data = data;
});

Обратите внимание, что это также означает, что не можно установить функцию стрелки this с .bind или .call.

Если вы не очень знакомы с this, рассмотрим чтение

2. Функции стрелок не могут быть вызваны с помощью new

ES2015 различает функции, доступные call , и функции, которые являются конструкцией . Если функция конструируется, ее можно вызвать с помощью new, то есть new User(). Если функция является вызываемой, ее можно вызвать без new (т. Е. Вызов нормальной функции).

Функции, созданные посредством деклараций / выражений функций, являются конструктивными и вызываемыми. Функции стрелок (и методы) являются только вызываемыми. class конструкторы только конструктивны.

Если вы пытаетесь вызвать функцию, не вызываемую вызовом, или построить неконструируемую функцию, вы получите ошибку времени выполнения.


Зная это, мы можем указать следующее.

Сменный:

  • Функции, которые не используют this или arguments.
  • Функции, которые используются с .bind(this)

Не сменный:

  • Функции конструктора
  • Функция / методы, добавленные к прототипу (поскольку они обычно используют функции this)
  • Variadic (если они используют arguments (см. ниже))

Давайте рассмотрим это более подробно с помощью ваших примеров:

Функция конструктора

Это не будет работать, потому что функции стрелок нельзя вызвать с помощью new. Продолжайте использовать объявление / выражение функции или используйте class.

Способы прототипа

Скорее всего нет, потому что методы прототипа обычно используют this для доступа к экземпляру. Если они не используют this, вы можете его заменить. Однако, если вы в первую очередь заботитесь о сжатом синтаксисе, используйте class с его синтаксисом сжатого метода:

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

Методы объекта

Аналогично для методов в объектном литерале. Если метод хочет ссылаться на сам объект через this, продолжайте использовать функциональные выражения или используйте новый синтаксис метода:

const obj = {
  getName() {
    // ...
  },
};

Обратные вызовы

Это зависит. Вы должны обязательно заменить его, если вы наложили внешний this или используете .bind(this):

// old
setTimeout(function() {
  // ...
}.bind(this), 500);

// new
setTimeout(() => {
  // ...
}, 500);

Но: Если код, вызывающий обратный вызов, явно устанавливает this на определенное значение , как это часто бывает с обработчиками событий, особенно с jQuery, и обратный вызов использует this (или arguments), вы не можете использовать функцию стрелки!

Variadic функции

Поскольку функции стрелок не имеют собственных arguments, вы не можете просто заменить их функцией стрелки. Однако ES2015 вводит альтернативу использованию arguments: параметр rest .

// old
function sum() {
  let args = [].slice.call(arguments);
  // ...
}

// new
const sum = (...args) => {
  // ...
};

Связанный вопрос:

Дополнительные ресурсы:

130
задан AnimaSola 2 April 2013 в 13:51
поделиться

5 ответов

Вы пытались просто добавить еще один Include:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Include(i => i.Lab)
                .Single(x => x.Id == id);

Ваше решение не работает, потому что Include не принимает логический оператор

Include(i => i.Modules.Select(s => s.Chapters) &&          i.Lab)
                           ^^^                  ^             ^ 
                          list           bool operator    other list

Update Чтобы узнать подробнее, загрузите LinqPad и просмотрите образцы. Я думаю, что это самый быстрый способ познакомиться с Linq и Lambda.

В начале - разница между Select и Include заключается в том, что с помощью Select вы решили , что вы хотите вернуться (aka projection). Include - это функция Eager Loading , которая сообщает Entity Framework, что вы хотите включить данные из других таблиц.

Синтаксис Include также может быть в строке. Например:

           db.Courses
            .Include("Module.Chapter")
            .Include("Lab")
            .Single(x => x.Id == id);

Но примеры в LinqPad объясняют это лучше.

205
ответ дан J Bryan Price 19 August 2018 в 01:24
поделиться
  • 1
    Ценить это! Где я могу узнать больше об этом? Меня особенно интересует разница между Include и Select – AnimaSola 3 April 2013 в 03:37
  • 2
    @AnimaSola Я обновил свой ответ – Jens Kloster 3 April 2013 в 06:58
  • 3
    Только для меня это работало: .Include("Module.Chapter"). Любая идея, почему? – Jo Smo 2 August 2015 в 17:19
  • 4
    @JoSmo вам нужно импортировать пространство имен System.Data.Enity для доступа к методу extensionmethod. подробнее здесь – Jens Kloster 2 August 2015 в 18:37
  • 5
    рекомендуется для упоминания блестящей linqpad и подсказки для использования System.Data.Entity, thx Jens – Mike 31 August 2016 в 09:36

Include является частью свободного интерфейса, поэтому вы можете писать несколько Include операторов, следующих за другими

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 
21
ответ дан Ilya Ivanov 19 August 2018 в 01:24
поделиться
  • 1
    ценить это! не могли бы вы указать мне, где я могу узнать больше об этом? Благодаря! – AnimaSola 2 April 2013 в 18:35
  • 2
    Вы знаете, что такое синтаксис, если модули имеют несколько таблиц, к которым вы хотите присоединиться? Скажите, что это ссылки на главы и что-то еще? – David Spence 5 August 2015 в 10:27
  • 3
    Является ли свободная часть .Net или это библиотека, которая должна быть установлена? – codea 6 December 2015 в 09:55

Вы также можете попробовать

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
16
ответ дан Martin Larsson 19 August 2018 в 01:24
поделиться

Можно написать метод расширения следующим образом:

    /// <summary>
    /// Includes an array of navigation properties for the specified query 
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <param name="query">The query to include navigation properties for that</param>
    /// <param name="navProperties">The array of navigation properties to include</param>
    /// <returns></returns>
    public static IQueryable<T> Include<T>(this IQueryable<T> query, params string[] navProperties)
        where T : class
    {
        foreach (var navProperty in navProperties)
            query = query.Include(navProperty);

        return query;
    }

И использовать его так, как это, даже в общей реализации:

string[] includedNavigationProperties = new string[] { "NavProp1.SubNavProp", "NavProp2" };

var query = context.Set<T>()
.Include(includedNavigationProperties);
1
ответ дан Mohsen Afshin 19 August 2018 в 01:24
поделиться
  • 1
    Я пробовал ваш ответ, но он бросает stackoverflowExceptions из-за бесконечного цикла с собой. – Victoria S. 9 November 2016 в 13:28
  • 2
    @VictoriaS., Вы можете переименовать метод расширения, чтобы он не мешал реальному Include – Mohsen Afshin 9 November 2016 в 20:52

В ядре Entity Framework Core (EF.core) вы можете использовать .ThenInclude для включения следующих уровней.

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .ToList();

Дополнительная информация: https://docs.microsoft.com/ru -us / ef / core / querying / related-data

Примечание: Предположим, вам нужно несколько ThenInclude() на blog.Posts, просто повторите Include(blog => blog.Posts) и сделать еще ThenInclude(post => post.Other).

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Other)
 .ToList();
11
ответ дан Nick N. 19 August 2018 в 01:24
поделиться
  • 1
    В EF.core я, похоже, не могу сделать .Include (i = & gt; i.Modules.Select (s = & gt; s.Chapters)), в частности. Выбрать внутри .Include. Может ли кто-нибудь подтвердить или поговорить? – ttugates 16 December 2017 в 14:43
  • 2
    @ttugates Что вы намерены делать с этим выбором? Я думаю, что вы хотите сделать именно то, что вы делаете с ThenInclude в ядре EF. Возможно, поставим вопрос с хорошим примером, чтобы мы могли ответить на него. – Nick N. 18 December 2017 в 15:05
  • 3
    @Nick N - Entity Framework Linq Query: Как найти объекты с несколькими свойствами Nav и выбрать из свойства 3-го Nav . Поскольку то, что я выбрал, не соответствует тем, с чем я согласен, в него нет необходимости, поэтому вопрос тангенциальный. Мой вопрос может быть слишком «узким». но оцените любую помощь. – ttugates 18 December 2017 в 15:32
Другие вопросы по тегам:

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