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

C# Web Api,更新数据库,连接重置200ok,c#,asp.net,database,asp.net-web-api,connection-reset,C#,Asp.net,Database,Asp.net Web Api,Connection Reset,我有asp.NETWebAPI应用程序。我在数据库中有表companys,它有两个字段:id和description。最近,我更新了数据库并添加了一个名为CustomerID的新列。在那之后当我打电话给公司的时候 private readonly BackendContext _context; public CompaniesController(BackendContext context) { _context = context; } // GET: api/Companie

我有asp.NETWebAPI应用程序。我在数据库中有表companys,它有两个字段:id和description。最近,我更新了数据库并添加了一个名为CustomerID的新列。在那之后当我打电话给公司的时候

private readonly BackendContext _context;

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

// GET: api/Companies
[HttpGet]
public IEnumerable<Company> GetCompanies()
{
    return _context.Companies;
}
但我也得到了表中未指定的字段:customer、CompanysToProducts、invoices。发票和公司产品是我数据库中的表,我不知道客户指的是什么。我还应该提到,这些表是通过外键连接的。

更新
错误:

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

我只想返回有关公司的数据,但控制器还返回另一个字段,如customer、CompanysToProducts、invoices

虽然直接从数据上下文返回很方便,但这会带来额外的副作用,即将API与数据库(以及数据访问框架,这似乎是本文的问题)耦合在一起。在API设计中,明确定义API的“形状”通常是一个好主意。要返回的字段等

将结果投影到显式定义的形状中,并仅返回要返回的内容:

var result = _context.Companies
                     .Select(c => new 
                     {
                         c.ID,
                         c.Name,
                         c.Description,
                         c.CustomerID
                     })
                     .ToList();
public class CompanyViewModel
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public int CustomerID { get; set; }
}
这具体定义了您想要返回的内容,只从备份数据中获取信息,将其具体化为内存中列表,最后通过API返回

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

就像任何事情一样,这是一种平衡。在任何一个方向上走得太远,那个方向开始成为一个问题。就我个人而言,我经常选择定义要返回的视图模型:

var result = _context.Companies
                     .Select(c => new 
                     {
                         c.ID,
                         c.Name,
                         c.Description,
                         c.CustomerID
                     })
                     .ToList();
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项目中,并且这是您唯一拥有的项目,那么您会强烈希望返回这些模型

另一种选择是:


但请记住,这仍然会将您的API与您的DB模型相耦合。在这个项目中,这可能没什么问题,但是如果你在数据库中添加了一列你不想让用户看到的内容,那么这就成了一个问题。与其他方法一样,您也有选择。

这可能是相关的:如果您的模型具有循环引用,则可能无法序列化。如果将
.ToList()
附加到要返回的集合,会发生什么情况?或者使用
.Select()
将其投影到一个匿名类型,以指定所需的确切属性?@David当我这样做时,我收到服务器错误:return\u context.companys.ToList();类似于相关问题中的启动修改不会进行任何更改在搞乱启动之前,我建议将模型投影到特定的值子集中。毕竟,如果这些模型引用了其他模型,这些模型引用了其他模型,等等,那么您真的希望在这个API调用中返回那么多数据吗?具体返回哪些字段?@David我只想返回有关公司的数据,但控制器还返回另一个字段,如customer、companyistoproducts、invoices(我更新了帖子),这些字段在修改数据库之前没有出现在回复中。而且它只返回第一个公司。我应该编辑之前返回的数据是正确的,没有添加ToList()等。你能帮我处理我更新到帖子中的类型错误吗,请。还有一个问题:这样的回答是否意味着我的数据库有问题?也谢谢你lot@Storm:哦,我忽略了退货类型。很抱歉:)在这种情况下,我通常会定义一个视图模型,并将其投影到该视图模型中以返回。这是一种在重复代码(具有非常相似的模型和视图模型)与将DB框架作为API模型进行争论之间的权衡。DB本身并没有什么问题,只是EF创建的模型树比您通常希望API返回的模型树更大、更复杂。
return _context.Companies
               .Select(c => new CompanyViewModel
               {
                   ID = c.ID,
                   Name = c.Name,
                   Description = c.Description,
                   CustomID = c.CustomerID
               })
               .ToList();
services.AddMvc()
          .AddJsonOptions(
                options => options.SerializerSettings.ReferenceLoopHandling
                    = Newtonsoft.Json.ReferenceLoopHandling.Ignore );