Web Api, обновление БД, сброс подключения 200ок - PullRequest
0 голосов
/ 23 декабря 2018

У меня есть приложение asp.net web api.У меня есть таблица Companies в базе данных, которая имеет два поля: id и description.Недавно я обновил базу данных и добавил новый столбец с именем CustomerID.После этого, когда я пытаюсь вызвать getCompanies

private readonly BackendContext _context;

public CompaniesController(BackendContext context)
{
    _context = context;
}

// GET: api/Companies
[HttpGet]
public IEnumerable<Company> GetCompanies()
{
    return _context.Companies;
}

, я получаю

enter image description here

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

Дополнительный код: Context

public class BackendContext : Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext<IdentityUser>//DbContext
    {
        public BackendContext(DbContextOptions<BackendContext> options) : base(options) { }

        public DbSet<Company> Companies { get; set; }
        public DbSet<CompanyToProduct> CompanyToProducts { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Vendor> Vendors { get; set; }
        public DbSet<VendorToProduct> VendorToProducts { get; set; }
        public DbSet<Invoice> Invoices { get; set; }
        public DbSet<InvoiceItem> InvoiceItems { get; set; }

    }

Модель

public class Company
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

        public int CustomerID { get; set; }
        public virtual Customer Customer { get; set; }

        public virtual ICollection<CompanyToProduct> CompaniesToProducts { get; set; }
        public virtual ICollection<Invoice> Invoices { get; set; }
    }

ОБНОВЛЕНИЕ Я добавил несколькозначения в таблицу и я получил ответ первой компании:

[{"id":1,"name":"Google","description":"free food","customerID":6,"customer":null,"companiesToProducts":null,"invoices":null}

НО я также получил поля, которые не указаны в таблице: customer, companiesToProducts, счета-фактуры.Счета-фактуры и companiesToProducts - это таблицы в моей базе данных, и я не знаю, на что ссылается клиент.Следует также отметить, что эти таблицы связаны внешним ключом.enter image description here

enter image description here

ОБНОВЛЕНИЕ
Ошибка: enter image description here

1 Ответ

0 голосов
/ 23 декабря 2018

Судя по комментариям к вышеуказанному вопросу, похоже, что все связанные таблицы пытаются сериализоваться, и общий процесс, вероятно, дает сбой из-за циклических ссылок в графе объектов.Этот комментарий выше, в частности, намекает на решение:

Я хочу вернуть только данные о компаниях, но контроллер также возвращает другие поля, такие как customer, companiesToProducts, счета-фактуры

Хотя удобно просто вернуться непосредственно из контекста данных, это имеет дополнительный побочный эффект соединения API с базой данных ( и с каркасом доступа к данным, что, по-видимому, является проблемой здесь).В общем, в дизайне API всегда хорошая идея явно определить «форму» этого API.Возвращаемые поля и т. Д.

Проецируйте ваш результат в явно заданную форму и верните только то, что вы хотите вернуть:

var result = _context.Companies
                     .Select(c => new 
                     {
                         c.ID,
                         c.Name,
                         c.Description,
                         c.CustomerID
                     })
                     .ToList();

Это конкретно определяет, что вы хотите вернуть, только выборкиэта информация из вспомогательных данных материализует ее в список в памяти и, наконец, затем возвращает ее через API.

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

Как и во всем, это баланс.Слишком далеко в любом направлении, и это направление начинает становиться проблемой.Лично я часто иду по пути определения возвращаемой модели представления:

public class CompanyViewModel
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public int CustomerID { get; set; }
}

и возврата этого:

return _context.Companies
               .Select(c => new CompanyViewModel
               {
                   ID = c.ID,
                   Name = c.Name,
                   Description = c.Description,
                   CustomID = c.CustomerID
               })
               .ToList();

Но обычно я делаю это потому, что я обычно работаю всреда, в которой веб-приложение - это всего лишь одно приложение, подключенное к общему общему бизнес-домену, поэтому модели представлений не похожи на дублирование кодаОни находятся в отдельном проекте, часто имеют иную форму, нежели вспомогательные объекты данных, и т. Д. Но если ваши доменные модели уже есть в вашем веб-проекте, и это единственный проект, который у вас есть, очень хочется их вернуть.

Другой вариант , когда это так, может быть универсально настроить сериализацию JSON на игнорирование циклических ссылок :

services.AddMvc()
          .AddJsonOptions(
                options => options.SerializerSettings.ReferenceLoopHandling
                    = Newtonsoft.Json.ReferenceLoopHandling.Ignore );

Но оставайтесь вИмейте в виду, что это все еще связывает ваш API с вашими моделями БД.Может быть, это нормально в этом проекте, но если вы когда-нибудь добавите в свою БД столбец, который вы не хотите, чтобы пользователи видели, тогда это станет проблемой.Как и во всем, у вас есть варианты.

...