Web Api,更新数据库,连接重置 200ok

Web Api, Update DB, connection reset 200ok

我有 asp.net 网络 api 应用程序。我在数据库中有 table 公司,它们有两个字段: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;
}

我明白了

我认为控制器试图 return 旧公司模型但无法实现它,因为它现在不存在但我不知道如何解决这个问题,尽管控制器应该 return更新的模型。也许我应该以某种方式重建应用程序以使其使用更新版本?

附加代码: 上下文

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; }
    }

更新 我在 table 中添加了一些值,我得到了第一家公司的回复:

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

但我还得到了 table 中未指定的字段:客户、companiesToProducts、发票。发票和 companiesToProducts 在我的数据库中是 table,我不知道客户指的是什么。我还应该提到这些 tables 是通过外键连接的。

更新
错误:

根据对上述问题的评论,听起来相关表都在尝试序列化并且整个过程可能由于对象图中的循环引用而失败。上面的评论特别暗示了一个解决方案:

I want to return only the data about companies but the controller also returns another fields like customer, companiesToProducts,invoices

虽然直接从数据上下文中 return 很方便,但这会增加 API 与数据库耦合的副作用( 与数据访问框架,这似乎是这里的问题)。一般来说,在 API 设计中,显式定义 API 的 "shape" 总是一个好主意。 return 等字段

将您的结果投影到明确定义的形状中,并且 return 只是您想要的 return:

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

这具体定义了您想要 return 的内容,仅从支持数据中获取该信息,将其具体化到内存列表中,最后 return 通过 API.

然而,这有一个潜在的缺点。因为现在我们还需要更改 return 方法的 API 类型。那里有几个选项,例如 return 创建一个通用响应对象或创建一个非常接近您现有模型并开始感觉像重复的视图模型。

与任何事情一样,这是一种平衡。在任何一个方向上走得太远,那个方向就会开始成为一个问题。就我个人而言,我经常将视图模型定义为 return:

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

和return认为:

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

但我通常这样做的原因是因为我通常在 Web 应用程序只是附加到公共共享业务域的一个应用程序的环境中工作,因此视图模型感觉不像代码重复。它们在一个单独的项目中,通常采用与支持数据对象等不同的形状。但是如果您的域模型已经在您的 Web 项目中并且这是您拥有的唯一项目,那么强烈希望 return那些。

另一种选择如果是这种情况可能是 :

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

但请记住,这仍然会将您的 API 耦合到您的数据库模型。也许在这个项目中这没问题,但是如果您向数据库中添加了一个您不希望用户看到的列,那么它就会成为一个问题。与任何事情一样,您有多种选择。