【问题标题】:Web Api, Update DB, connection reset 200okWeb Api,更新数据库,连接重置 200ok
【发布时间】:2018-12-23 13:34:30
【问题描述】:

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

我明白了

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

附加代码: 上下文

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}

但我也得到了表中未指定的字段:客户、公司到产品、发票。 Invoices 和 CompaniesToProducts 是我数据库中的表,我不知道客户指的是什么。我还应该提到这些表是通过外键连接的。

更新
错误:

【问题讨论】:

  • 这可能是相关的:stackoverflow.com/questions/44322809/… 如果您的模型有循环引用,它可能无法序列化。如果将.ToList() 附加到要返回的集合中会发生什么?或者使用.Select() 将其投影为匿名类型以指定您想要的确切属性?
  • @David 当我这样做时收到服务器错误:return _context.Companies.ToList();像相关问题中的启动修改不会改变
  • 在搞乱这家初创公司之前,我建议将模型投影到特定的值子集中。毕竟,如果这些模型引用了其他模型,哪些模型引用了其他模型等等,那么您真的希望在这个 API 调用中返回 那么多 数据吗?你具体要返回的字段是什么?
  • @David 我只想返回有关公司的数据,但控制器还返回其他字段,例如客户、companyToProducts、发票(我已经更新了帖子),这些字段在数据库修改之前不在响应中。它也只返回第一家公司。我应该编辑以前正确返回的数据而不添加 ToList() 等。

标签: c# asp.net database asp.net-web-api connection-reset


【解决方案1】:

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

我只想返回有关公司的数据,但控制器还返回其他字段,如客户、companyToProducts、发票

虽然直接从数据上下文返回很方便,但这增加了将 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();

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

另一种选择在这种情况下可能是universally set your JSON serialization to ignore circular references

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

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

【讨论】:

  • 你能帮我处理我更新到帖子的类型错误吗,请。还有一个问题:这样的反应是否意味着我的数据库有问题?也非常感谢
  • @Storm:哦,我忽略了返回类型。对此感到抱歉:) 在这种情况下,我通常会定义一个视图模型并将其投影到该视图模型中以返回。这是在重复代码(具有非常相似的模型和视图模型)与将 DB 框架作为 API 模型争论之间的一种权衡。数据库本身并没有什么问题,只是 EF 创建的模型树比您通常希望 API 返回的模型树更大且涉及更多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 2011-02-02
  • 2011-03-26
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多