Предоставление отношений «многие ко многим» с использованием GraphQL.EntityFramework - PullRequest
0 голосов
/ 28 января 2020

У меня довольно прямолинейное представление. NET Модель Core EF, поддерживаемая SQL Серверной базой данных, которую я работаю, чтобы показать через GraphQL в. NET Core Web API с использованием GraphQL.EntityFramework (который в свою очередь основывается на GraphQL для. NET).

У меня есть несколько отношений "многие ко многим", таких как это:

Many-to-many relation between stores and categories

Модель сущности имеет такую ​​форму (для ясности удалены несущественные биты):

public class StoreEntity
{
    [Key]
    public int StoreId { get; set; }
    public string Name { get; set; }

    // etc...

    public List<StoreCategoryEntity> Categories { get; set; }
}

public class StoreCategoryEntity
{
    [Required]
    public int StoreId { get; set; }
    [Required]
    public int CategoryId { get; set; }

    public CategoryEntity Category { get; set; }
}

public class CategoryEntity
{
    [Key]
    public int CategoryId { get; set; }
    public string Name { get; set; }
}

... потому что так нравится EF (и это имеет смысл).

Теперь я хотел бы представить это как GraphQL в этой форме:

query {
  store (id:1) {
    storeId
    name
    categories {
      categoryId
      name
    }
  }
}

Используя GraphQL.EntityFramework, типичный тип графов объектов будет выглядеть примерно так (это является конструктором):

public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
    Field(x => x.StoreId).Description("The store ID");
    Field(x => x.Name).Description("The store name");

    // ...

    AddNavigationListField(
        name: "categories",
        resolve: context => context.Source.Categories);
}

Теперь для этого требуется тип граф объекта для StoreCategory, и форма графика будет выглядеть следующим образом:

query {
  store (id:1) {
    storeId
    name
    categories {
      storeId
      categoryId
      category {
        categoryId
        name
      }
    }
  }
}

Это работает нормально, но несколько более запутанный, чем мне бы хотелось. Я хотел бы, чтобы поле списка навигации было типа Category, а не StoreCategory. Я пробовал это:

public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
    Field(x => x.StoreId).Description("The store ID");
    Field(x => x.Name).Description("The store name");

    AddNavigationListField(
        name: "categories",
        resolve: context => context.Source.Categories.Select(x => x.Category));
}

... но возвращаются все категории null. Кажется, GraphQL.EntityFramework, который пытается понять, что EF «включает» (и в основном успешно), не понимает необходимости включать Category.

Может ли кто-нибудь с опытом использования GraphQL.EntityFramework дать мне указатель здесь?

Редактировать:

Мне удалось заставить его работать так:

Field<ListGraphType<CategoryType>>(
    name: "categories",
    resolve: context =>
    {
        var dbContext = ResolveDbContext(context);
        return dbContext.StoreCategories
            .AsNoTracking()
            .Include(x => x.Category)
            .Where(x => x.StoreId == context.Source.StoreId)
            .Select(x => x.Category);
    });

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

1 Ответ

1 голос
/ 29 января 2020

Это работает:

public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
    Field(x => x.StoreId).Description("The store ID");
    Field(x => x.Name).Description("The store name");

    // ...

    AddNavigationListField(
        name: "categories",
        resolve: context => context.Source.Categories.Select(x => x.Category),
        includeNames: new[] { "Categories.Category" })
        .Description = "The categories for the store";

}

Хитрость заключается в использовании точечного формата для включений, который позволяет определить «путь» включения.

Причина, по которой это необходимо, заключается в том, что пока GraphQL.EntityFramework будет применять все включения в массиве аргументов includeNames, все они применяются на уровне исходного объекта (здесь: Store) - прямой поддержки .ThenInclude().

"Categories.Category" нет. эквивалентно .Include(x => x.Categories).ThenInclude(x => x.Category).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...