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

Примечание.

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

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

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

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

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

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

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

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

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

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

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

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

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

Сопоставление типа сущности без ключа с объектом базы данных достигается с помощью ToTable API или ToView api fluent. С точки зрения 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; }
}

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

db.Database.ExecuteSqlRaw(
    @"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 = db.BlogPostCounts.ToList();

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

Совет

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

Совет

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