Поделиться через


Типы сущностей без ключа

Замечание

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

Помимо обычных типов сущностей модель EF Core может содержать типы сущностей без ключей, которые можно использовать для выполнения запросов базы данных к данным, которые не содержат значения ключей.

Определение типов сущностей без ключей

Типы сущностей без ключей можно определить следующим образом:

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Типы сущностей без ключей

Типы сущностей без ключей поддерживают многие из тех же возможностей сопоставления, что и обычные типы сущностей, такие как сопоставление наследования и свойства навигации. В реляционных хранилищах они могут настраивать целевые объекты и столбцы базы данных с помощью методов Fluent API или аннотаций данных.

Однако они отличаются от обычных типов сущностей в том, что они:

  • Не удается определить ключ.
  • Никогда не отслеживаются изменения в DbContext и поэтому никогда не вставляются, обновляются или удаляются в базе данных.
  • Никогда не обнаруживаются по соглашению.
  • Поддерживается лишь ограниченное количество функций сопоставления навигации, в частности:
    • Они не должны никогда выступать в качестве основной цели отношений.
    • Возможно, у них нет навигации по принадлежащим сущностям
    • Они могут содержать только свойства ссылочной навигации, указывающие на обычные сущности.
    • Сущности не могут содержать свойства навигации для типов сущностей без ключа.
  • Необходимо настроить с помощью аннотации данных [Keyless] или метода .HasNoKey() вызова.
  • Может быть сопоставлено с определяющим запросом. Определяющий запрос — это запрос, объявленный в модели, который выступает в качестве источника данных для типа сущности без ключа.
  • Может иметь иерархию, но ее необходимо сопоставить с TPH.
  • Не удается использовать разделение таблиц или разделение сущностей.

Сценарии использования

Ниже приведены некоторые основные сценарии использования для типов сущностей без ключа:

  • Выступая в качестве возвращаемого типа для запросов SQL.
  • Сопоставление представлений базы данных, не содержащих первичный ключ.
  • Сопоставление с таблицами, у которых не определен первичный ключ.
  • Сопоставление с запросами, определенными в модели.

Сопоставление с объектами базы данных

Сопоставление типа сущности без ключа с объектом базы данных осуществляется с помощью fluent API ToTable или ToView. С точки зрения EF Core объект базы данных, указанный в этом методе, представляет собой представление, то есть он рассматривается как источник запросов только для чтения и не может быть целевым объектом операций обновления, вставки или удаления. Однако это не означает, что объект базы данных действительно должен быть представлением базы данных. Кроме того, она может быть таблицей базы данных, которая будет рассматриваться как доступная только для чтения. И наоборот, для обычных типов сущностей EF Core предполагает, что объект базы данных, указанный в ToTable методе, можно рассматривать как таблицу, что означает, что он может использоваться в качестве источника запросов, но также предназначен для операций обновления, удаления и вставки. Фактически, можно указать имя представления базы данных ToTable, и все должно работать нормально, если представление настроено так, чтобы быть обновляемым в базе данных.

Пример

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

Подсказка

Вы можете скачать используемый в этой статье пример из репозитория GitHub.

Сначала мы определим простую модель блога и записи:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
}

Далее мы определим простое представление базы данных, позволяющее запрашивать количество записей, связанных с каждым блогом:

await db.Database.ExecuteSqlRawAsync(
    @"CREATE VIEW View_BlogPostCounts AS
                SELECT b.Name, Count(p.PostId) as PostCount
                FROM Blogs b
                JOIN Posts p on p.BlogId = b.BlogId
                GROUP BY b.Name");

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

public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Затем мы настраиваем тип сущности без ключа в OnModelCreating с помощью HasNoKey API. Мы используем API конфигурации fluent для настройки сопоставления для типа сущности без ключей:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<BlogPostsCount>(
            eb =>
            {
                eb.HasNoKey();
                eb.ToView("View_BlogPostCounts");
                eb.Property(v => v.BlogName).HasColumnName("Name");
            });
}

Затем мы настроим DbContext на включение DbSet<T>.

public DbSet<BlogPostsCount> BlogPostCounts { get; set; }

Наконец, мы можем запросить представление базы данных стандартным способом:

var postCounts = await db.BlogPostCounts.ToListAsync();

foreach (var postCount in postCounts)
{
    Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
    Console.WriteLine();
}

Подсказка

Обратите внимание, что мы также определили свойство запроса уровня контекста (DbSet), которое будет выступать в качестве корневого элемента для запросов к этому типу.

Подсказка

Чтобы протестировать типы сущностей без ключа, сопоставленные с представлениями с помощью поставщика в памяти, сопоставите их с запросом через ToInMemoryQuery. Дополнительные сведения см. в документации поставщика в памяти .