Запросы и поиск сущностей

В этом разделе рассматриваются различные способы запроса данных с помощью Entity Framework, включая LINQ и метод Find. Методы, показанные в этом разделе, применяются одинаково к моделям, созданным с помощью code First и ef Designer.

Поиск сущностей с помощью запроса

DbSet и IDbSet реализуют IQueryable и поэтому можно использовать в качестве отправной точки для написания запроса LINQ к базе данных. Это не подходящее место для подробного обсуждения LINQ, но вот несколько простых примеров:

using (var context = new BloggingContext())
{
    // Query for all blogs with names starting with B
    var blogs = from b in context.Blogs
                   where b.Name.StartsWith("B")
                   select b;

    // Query for the Blog named ADO.NET Blog
    var blog = context.Blogs
                    .Where(b => b.Name == "ADO.NET Blog")
                    .FirstOrDefault();
}

Обратите внимание, что DbSet и IDbSet всегда создают запросы к базе данных и всегда будут включать круговую поездку в базу данных, даже если возвращаемые сущности уже существуют в контексте. Запрос выполняется в базе данных, когда:

  • Он перечисляется инструкцией foreach (C#) или For Each (Visual Basic).
  • Она перечисляется операцией сбора, например ToArray, ToDictionary или ToList.
  • Операторы LINQ, такие как First или Any , указываются в самой внешней части запроса.
  • Вызываются следующие методы: метод расширения Load для DbSet, DbEntityEntry.Reload и Database.ExecuteSqlCommand.

Когда результаты возвращаются из базы данных, объекты, которые не существуют в контексте, присоединяются к контексту. Если объект уже находится в контексте, возвращается существующий объект (текущие и исходные значения свойств объекта в записи не перезаписываются значениями базы данных).

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

Если запрос не возвращает строк из базы данных, результат будет пустой коллекцией, а не null.

Поиск сущностей с помощью первичных ключей

Метод Find в DbSet использует значение первичного ключа для попытки найти сущность, отслеживаемую контекстом. Если сущность не найдена в контексте, запрос будет отправлен в базу данных, чтобы найти сущность там. Значение NULL возвращается, если сущность не найдена в контексте или в базе данных.

Поиск отличается от использования запроса двумя значительными способами:

  • Круговая поездка в базу данных будет выполнена только в том случае, если сущность с заданным ключом не найдена в контексте.
  • Поиск вернет сущности, которые находятся в состоянии "Добавлено". То есть Find вернет сущности, которые были добавлены в контекст, но еще не сохранены в базе данных.

Поиск сущности по первичному ключу

В следующем коде показаны некоторые виды использования Find:

using (var context = new BloggingContext())
{
    // Will hit the database
    var blog = context.Blogs.Find(3);

    // Will return the same instance without hitting the database
    var blogAgain = context.Blogs.Find(3);

    context.Blogs.Add(new Blog { Id = -1 });

    // Will find the new blog even though it does not exist in the database
    var newBlog = context.Blogs.Find(-1);

    // Will find a User which has a string primary key
    var user = context.Users.Find("johndoe1987");
}

Поиск сущности по составным первичным ключам

Entity Framework позволяет сущностям иметь составные ключи — это ключ, состоящий из нескольких свойств. Например, у вас может быть сущность BlogSettings, представляющая параметры пользователей для определенного блога. Так как у пользователя будет только один blogSettings для каждого блога, вы можете сделать первичный ключ BlogSettings сочетанием BlogId и имени пользователя. Следующий код пытается найти BlogSettings с BlogId = 3 и имя пользователя = "johndoe1987":

using (var context = new BloggingContext())
{
    var settings = context.BlogSettings.Find(3, "johndoe1987");
}

Обратите внимание, что при наличии составных ключей необходимо использовать ColumnAttribute или API fluent, чтобы указать порядок свойств составного ключа. Вызов Find должен использовать этот порядок при указании значений, формающих ключ.