Выполнение эффективного запроса в отношении многих ко многим в EF Core - PullRequest
0 голосов
/ 22 января 2019

В Entity Framework Core можно установить отношение многие-ко-многим через таблицу соединений.

Я не знаю, как эффективно запросить подобные отношения. Учитывая приведенные ниже ссылочные отношения, у меня есть сущность Post, а коллекция PostTags равна нулю. Я хочу загрузить все Tag, связанные с Post, и лучшее, что у меня есть, - это что-то похожее на это:

void GetAllTags(Post somePost)
{
    await dbContext.Entry(somePost)
        .Collection(p => p.PostTags)
        .LoadAsync();
    foreach(var postTag in somePost.PostTags)
    {
        await dbContext.Entry(postTag)
            .Reference(p => p.Tag)
            .LoadAsync();
    }
}

Я действительно предпочел бы вернуть ICollection<Tag> через один запрос к БД.


Это справочная реализация из Отношения - EF Core | Документы Microsoft

class MyContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
    public DbSet<Tag> Tags { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<PostTag>()
            .HasKey(t => new { t.PostId, t.TagId });

        modelBuilder.Entity<PostTag>()
            .HasOne(pt => pt.Post)
            .WithMany(p => p.PostTags)
            .HasForeignKey(pt => pt.PostId);

        modelBuilder.Entity<PostTag>()
            .HasOne(pt => pt.Tag)
            .WithMany(t => t.PostTags)
            .HasForeignKey(pt => pt.TagId);
    }
}

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

    public List<PostTag> PostTags { get; set; }
}

public class Tag
{
    public string TagId { get; set; }

    public List<PostTag> PostTags { get; set; }
}

public class PostTag
{
    public int PostId { get; set; }
    public Post Post { get; set; }

    public string TagId { get; set; }
    public Tag Tag { get; set; }
}

1 Ответ

0 голосов
/ 22 января 2019

Если вам нужно только получить список тегов, связанных с публикацией, вы можете использовать простой запрос проекции. Просто начните с DbSet<> (т.е. EF Core IQueryable<>), а не с материализованного объекта / коллекции, например

ICollection<Tag> GetAllTags(Post somePost)
{
    return await dbContext.Set<PostTag>()
        .Where(pt => pt.PostId == somePost.PostId)
        .Select(pt => pt.Tag)
        .ToListAsync();
}

Если вы действительно хотите загрузить их в переданный экземпляр Post сущности, вы можете использовать комбинацию явной и активной загрузки с помощью Query метода:

void LoadAllTags(Post somePost)
{
    await dbContext.Entry(somePost)
        .Collection(p => p.PostTags)
        .Query()
        .Include(pt => pt.Tag)
        .LoadAsync();
}
...