Как я могу заставить мой API сгенерировать желаемые многоуровневые леса JSON? - PullRequest
2 голосов
/ 29 мая 2020

Вот так я хочу, чтобы мой объект JSON выглядел. Примечание: JSON ниже включает узел 'artworks', но я не могу его сгенерировать. Это проблема, которую я пытаюсь решить.

{
    "idArtist": 2,
    "artistName": "Alice Waters",
    "indexArtworks": [
        {
            "id": 2,
            "idArtist": 2,
            "idArtwork": 1,
            "artworks": [
                {
                    "idArtwork": 1,
                    "artworkTitle": "The Collaborative Artwork",
                }
            ]
        }
    ]
}

Ниже вставлена ​​диаграмма структуры моей таблицы. Синяя стрелка представляет существующий FK. Оранжевая стрелка представляет несуществующий FK, который был бы циклической ссылкой. На основе моих текущих знаний о том, как генерируется каркас. NET Core Web API JSON, чтобы создать JSON суб-подузел с использованием API _context.<Object>.Include().ThenInclude(), мне нужно будет определить FK с оранжевой стрелкой. Но это приведет к появлению циклической ссылки в БД, и моя попытка создать этот FK привела к ошибке.

Это мой структура таблицы, включая FK:

CREATE TABLE [dbo].[Artists](
    [ID_Artist] [int] NOT NULL,
    [Artist_Name] [nvarchar](255) NULL,
 CONSTRAINT [PK_Artists] PRIMARY KEY CLUSTERED 
(
    [ID_Artist] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

--------------------------------------------------------------------------------------------------------------------------------------------

CREATE TABLE [dbo].[Artworks](
    [ID_Artwork] [int] NOT NULL,
    [Artwork_Title] [nvarchar](255) NULL
 CONSTRAINT [PK_Artworks] PRIMARY KEY CLUSTERED 
(
    [ID_Artwork] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

--------------------------------------------------------------------------------------------------------------------------------------------

CREATE TABLE [dbo].[Index_Artworks](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ID_Artwork] [int] NOT NULL,
    [ID_Artist] [int] NOT NULL
 CONSTRAINT [PK_Index_Artworks] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Index_Artworks]  WITH CHECK ADD  CONSTRAINT [FK__Index_Art__ID_Ar__1C1305F7] FOREIGN KEY([ID_Artwork])
REFERENCES [dbo].[Artworks] ([ID_Artwork])
GO

ALTER TABLE [dbo].[Index_Artworks] CHECK CONSTRAINT [FK__Index_Art__ID_Ar__1C1305F7]
GO

ALTER TABLE [dbo].[Index_Artworks]  WITH CHECK ADD  CONSTRAINT [FK__Index_Art__ID_Ar__1D072A30] FOREIGN KEY([ID_Artist])
REFERENCES [dbo].[Artists] ([ID_Artist])
GO

ALTER TABLE [dbo].[Index_Artworks] CHECK CONSTRAINT [FK__Index_Art__ID_Ar__1D072A30]
GO

Это мой объект Artist в веб-API.

    public partial class Artists
    {
        public Artists()
        {
            IndexArtworks = new HashSet<IndexArtworks>();
        }

        public int Id { get; set; }
        public string ArtistName { get; set; }

        public virtual ICollection<IndexArtworks> IndexArtworks { get; set; }
    }

Здесь я я выдаю HttpGet в веб-API. Я указал на недопустимую строку ниже. Я понимаю, что это потому, что у объекта Artist нет оранжевого FK.

        // GET: api/Artists/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Artists>> GetArtists(int id)
        {
            var artists = await _context.Artists
                .Include(i => i.IndexArtworks)
                    .ThenInclude(i => i.Artworks) // <----------- this is not valid.
                .Where(i => i.Id == id)
                .FirstOrDefaultAsync();

            if (artists == null)
            {
                return NotFound();
            }

            return artists;
        }

Мой вопрос: Что мне нужно изменить в запросе API, объект Artist в API или таблицы и их взаимосвязи для включения подузла "artworks" в JSON?

Edits ------------- ----------------------------

@ Гуру Строн: Не уверен, понимаю ли я ваше предложение - пожалуйста поправьте меня если я ошибаюсь. FK между Index_Artworks и Artworks означает от Index_Artworks до Artworks. Мне нужно было бы создать FK, который указывает в противоположном направлении, но БД не позволит этого (а это круговая ссылка, поэтому это плохой дизайн).

Если ваше предложение не связано с созданием оранжевая стрелка FK, я сделал следующее обновление своего объекта IndexArtworks на уровне API: я добавил ссылку HashSet на Artworks и добавил virtual ICollection<Artworks>. Когда я раскомментировал .ThenInclude(i => i.Artworks) в своем ArtistController и запустил API, он дал мне следующую ошибку: SqlException: Invalid column name 'IndexArtworksId'. Invalid column name 'IndexArtworksId'. Я не знаю, о чем это, потому что я искал решение для IndexArtworksId и не смог его найти.

public partial class IndexArtworks
    {
        public IndexArtworks()
        {
            Artworks = new HashSet<Artworks>();
        }

        public int Id { get; set; }
        public int IdArtwork { get; set; }
        public int IdArtist { get; set; }
        public bool AVisibleYn { get; set; }
        public string AVisibleIdAdmin { get; set; }

        public virtual Artists IdArtistNavigation { get; set; }
        public virtual Artworks IdArtworkNavigation { get; set; }
        public virtual ICollection<Artworks> Artworks { get; set; }
    }

1 Ответ

1 голос
/ 29 мая 2020

Для использования ThenInclude оранжевое отношение не требуется. У вас уже есть FK от IndexArtworks до Artworks, так что это должно быть нормально:

class IndexArtworks
{
    public int ID { get; set; }
    public int ID_Artist { get; set; }
    public int ID_Artwork { get; set; }
    [ForeignKey("ID_Artist")]
    public virtual Artists Artist { get; set; }
    [ForeignKey("ID_Artwork")]
    public virtual Artworks Artwork { get; set; }
}

И запрос:

 var artists = await _context.Artists
            .Include(i => i.IndexArtworks)
                .ThenInclude(i => i.Artwork) 
            .Where(i => i.Id == id)
            .FirstOrDefaultAsync();

UPD

С вашими соглашениями об именах это должно выглядеть так:

public partial class IndexArtworks
{
    public int Id { get; set; }
    public int IdArtwork { get; set; }
    public int IdArtist { get; set; }
    public bool AVisibleYn { get; set; }
    public string AVisibleIdAdmin { get; set; }

    public virtual Artists IdArtistNavigation { get; set; }
    public virtual Artworks IdArtworkNavigation { get; set; }
}

И запрос:

 var artists = await _context.Artists
            .Include(i => i.IndexArtworks)
                .ThenInclude(i => i.IdArtworkNavigation) 
            .Where(i => i.Id == id)
            .FirstOrDefaultAsync();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...