是否可以在不创建 ViewModel 对象的情况下从 .NET 中的 REST api 获取复杂的实体框架对象? [英] Is it possible to get complex Entity Framework objects from a REST api in .NET without creating ViewModel objects?

查看:18
本文介绍了是否可以在不创建 ViewModel 对象的情况下从 .NET 中的 REST api 获取复杂的实体框架对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一组实体框架实体:

Imagine a set of Entity Framework entities:

public class Country {
    public string CountryCode { get; set; }
    public string Name { get; set; }
    public string Flag { get; set; }
}

public class Market {
    public string CountryCode { get; set; }
    public virtual Country Country { get; set; }
    public int ProductID { get; set; }      
    public virtual Product Product { get; set; }
}

public class Product {
    public int ProductID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Market> Markets{ get; set; }
}

想象一下还有一个 DOTNET 5 api GET

Imagine as well a DOTNET 5 api GET

// GET api/product
[HttpGet]
public async Task<IActionResult> GetProduct([FromRoute] int id)
{
    return Ok(await _context.Products
        .Include(p => p.Markets)
        .SingleAsync(m => m.ProductID == id));
}

如果没有附加到实体的市场,数据将毫无问题地返回,但是一旦我附加了一些链接项目,我就会收到错误消息:

If there are no markets attached to the entity the data returns without issue, but as soon as I have a few linked items attached I get an error:

HTTP 错误 502.3 - 错误的网关
指定的 CGI 应用程序遇到错误,服务器终止该进程.

HTTP Error 502.3 - Bad Gateway
The specified CGI application encountered an error and the server terminated the process.

我依稀记得以前的一个应用程序,其中每个复杂的 EF 对象都有一个仅限原始"类型的对象来向客户端发送和从客户端接收此对象,但我想知道是否有一种无需中间对象即可进行通信的方法?

I vaguely recall a previous application where every complex EF object had a "primitives only" type object to send and receive this object to and from the client, but I wonder if there is a way to communicate without intermediary objects?

例如:

public class ProductViewModel {
    public int ProductID { get; set; }
    public string Name { get; set; }
    public List<MarketViewModel> Markets{ get; set; }
}

public class MarketViewModel {
    public int ProductID { get; set; }
    public Country Country { get; set; }
}

我担心的是从客户端来回转换每个复杂对象的编码开销(我承认,我不确定这是否是一件坏事,也许无论如何都必须这样做).

My concern is the coding overhead of translating every complex object back and forth from the client (which, I'll admit, I'm not sure is even a bad thing, maybe it has to be done anyways).

由于脚手架 API 似乎直接获取和返回实体,我发现自己想知道是否有办法直接处理对象的复杂部分

Since the scaffolded APIs seem to take and return entities directly I find myself wondering if there is a way to handle the complex part of the object directly

编辑#1:

根据下面 Noel 的评论,如果我将导致错误的代码更改为

Per Noel's comment below, if I change the code which is causing the error to

    [HttpGet("{id}", Name = "GetProduct")]
    public async Task<IActionResult> GetProduct([FromRoute] int id)
    {

        Product product = await _context.Products
            .Include(t => t.Markets)
            .SingleAsync(m => m.ProductID == id);

        throw new System.Exception("error sample");
        return Ok(product);
    }

正确抛出堆栈跟踪.如果我删除异常,则会出现 500 网关错误.我同意它看起来可能是序列化错误,但很难说.

the stack trace is Correctly thrown. If I remove the exception, the 500 gateway error appears. I agree that it looks like it's probably a serialization error, but it's tough to say.

EDIT 2 - 根据 Oleg 下面的评论:

EDIT 2 - per a comment from Oleg below:

坏网关的解决方案是首先在 project.json 文件中的依赖项中显式更新 NewtonSoft.Json 的更新版本:

The solution to a bad gateway is to first explicitly update a more recent version of NewtonSoft.Json in the dependencies in the project.json file:

"dependencies": {
  "Newtonsoft.Json": "8.0.1-beta3",

接下来你必须修改Startup.cs文件

    public void ConfigureServices(IServiceCollection services)
    {

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

通过这两个设置,错误网关不再发生,并且 api 调用按预期成功返回复杂对象.

with those two settings in place, the bad gateway no longer occurs and an api call successfully returns the complex object as expected.

推荐答案

在我看来,您只是错过了 SingleAsync 调用中的 await.尝试使用

It seems to me that you just missed await in the call of SingleAsync. Try to use

[HttpGet]
public async Task<IActionResult> GetProduct([FromRoute] int id)
{
    return Ok(await _context.Products
        .Include(p => p.Markets)
        .SingleAsync(m => m.ProductID == id));
}

更新:我发现了问题.我建议您检查您可以检查 package.lock.json 以查看通过自动解析依赖项将加载哪个版本.那么我建议您在最新版本 8.0.1-beta3 到您项目的依赖项.另外你应该在SerializerSettings.ReferenceLoopHandling的配置中添加对Newtonsoft.Json.ReferenceLoopHandling.Ignore的设置.有关详细信息,请参阅问题.

UPDATED: I found the issue. I would recommend you to examine You can examine package.lock.json to see, which version will be loaded by automatic resolution of dependencies. Then I would you recommend to explicitly add Newtonsoft.Json in the latest version 8.0.1-beta3 to the dependencies of your project. Additionally you should add the setting of to Newtonsoft.Json.ReferenceLoopHandling.Ignore in the the configuration of SerializerSettings.ReferenceLoopHandling. See the issue for more details.

这篇关于是否可以在不创建 ViewModel 对象的情况下从 .NET 中的 REST api 获取复杂的实体框架对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆