ASP. NET 3.1 Web API, Entity Framework отношения один ко многим либо не созданы, либо заканчиваются циклом - PullRequest
0 голосов
/ 11 января 2020

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

Поскольку я впервые разрабатываю бэкэнд, я попробовал поискать в Google и нашел ASP. NET Core 3.1 Web API с Entity Framework "хорошим". (Я использую SQL Сервер в качестве сервера базы данных, если это уместно)

Теперь я пошел первым методом кода и создал таблицы с миграцией. ( ERD )

Я использовал встроенный инструмент для создания контроллеров.

Если я использовал это JSON для создания объекта записи (с HTTP POST), AuthorId и LocationId остаются на NULL (погоду я использую "" для номеров или нет). Я создал группу и пользователя, к которым она будет обращаться ранее.

JSON:

{
    "title": "Post",
    "posttext": "text",
    "creatorid": "1",
    "locationid": "1",
    "timeofpost": "2020-01-12"
}

Класс Post:


    using System;
    using System.Collections.Generic;

    namespace CedditBackend.Models
    {
        public class Post
        {
            public int Id { get; set; }
            public string Title { get; set; }
    #nullable enable
            public string? PostText { get; set; }
            public byte[]? Content { get; set; }
            public ICollection<Comment>? Comments { get; set; }
    #nullable disable
            public User Creator { get; set; }
            public Group Location { get; set; }
            public DateTime TimeOfPost { get; set; }

        }
    }

Сгенерированный HTTPPOST в контроллер:

    [HttpPost]
            public async Task<ActionResult<Post>> PostPost(Post post)
            {
                _context.Posts.Add(post);

                await _context.SaveChangesAsync();

                return CreatedAtAction("GetPost", new { id = post.Id }, post);
            }

С другой стороны, если я пытаюсь создать свой собственный класс записей из JSON (в основном десериализацию его), я получаю сообщение об ошибке "обнаружен цикл". Это я попробовал поискать в Google, но обнаружил, что в более ранней версии (я полагаю) я мог бы просто отключить это.

Тем не менее, если я открою базу данных, это показывает, что значения LocationId и AuthorId не равны NULL. , но если я пытаюсь получить сообщения пользователей (с помощью HTTP GET), все, что я получаю, это одно и то же сообщение об ошибке.

Мой переписанный HTTPPOST

    [HttpPost]
            public async Task<ActionResult<Post>> PostPost(Object obj)
            {
                Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(obj.ToString());

                Post post = new Post();
                post.Title = dict["title"].ToString();
                post.PostText = dict["posttext"].ToString();
                post.TimeOfPost = DateTime.Parse(dict["timeofpost"].ToString());
                post.Location = _context.Groups.FirstOrDefault(x => x.Id == int.Parse(dict["locationid"].ToString()));
                post.Creator = _context.Users.FirstOrDefault(x => x.Id == int.Parse(dict["creatorid"].ToString()));

                post.Creator.Posts.Add(post);
                post.Location.Posts.Add(post);

                _context.Posts.Add(post);

                await _context.SaveChangesAsync();

                return CreatedAtAction("GetPost", new { id = post.Id }, post);
            }

Я пытался прогнать весь этот материал несколькими способами, но ничего не нашел. Я что-то упускаю из виду?

Редактировать: класс User (который, я думаю, вызывает ссылку на цикл)

using System.Collections.Generic;

namespace CedditBackend.Models
{

        public class User
        {
            public int Id { get; set; }
            public string UserName { get; set; }
    #nullable enable
            public ICollection<Post>? Posts { get; set; } = new List<Post>();
            public ICollection<Comment>? Comments { get; set; } = new List<Comment>();
            public ICollection<UserGroup>? UserGroups { get; set; }
    #nullable disable

        }

}

Ответы [ 2 ]

0 голосов
/ 16 января 2020

Похоже, вы столкнулись с той же проблемой, что и я.

Новая JSON библиотека System.Text. JSON в настоящее время не может обрабатывать отношения «один ко многим», как кажется. В настоящее время они отслеживают проблему здесь , но исправление не запланировано до. NET 5. На данный момент я не нашел решения, но я обновлю этот ответ, если сделаю.

ОБНОВЛЕНИЕ Найден обходной путь, по крайней мере, на данный момент.

Установите Newtonsoft MVC Расширения

PM> Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.1.1

Редактируйте метод ConfigureServices в Startup.cs

services
    .AddControllers()
    .AddNewtonsoftJson()

Теперь настройте обработку l oop в Newtonsoft

services
    .AddControllers()
    .AddNewtonsoftJson(options =>
    {
      options.SerializerSettings.ReferenceLoopHandling = 
          Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    });

Этого должно быть достаточно, чтобы она заработала. Имейте в виду, что если у вас есть какие-либо пользовательские JsonConverters, вам придется перейти на преобразователи, предоставленные в библиотеке Newtonsoft, чтобы заставить их работать.

0 голосов
/ 11 января 2020

Попробуйте удалить эти строки.

post.Creator.Posts.Add(post);
post.Location.Posts.Add(post);

Вы уже определили Создателя и Местоположение вашего поста. Добавление его в свои коллекции сделало бы его круговой ссылкой.

...