GET 请求重置成员值

GET request resets member value

试图构建一个简单的 api,但 运行 遇到一个问题,即在 GET 请求后成员似乎被重置为默认值。有趣的是;我第一次发送请求时,返回了预期的结果,但是任何后续请求似乎都会导致一些数据丢失。为什么会这样?为什么第一次请求没有发生?我该如何解决?

(我正在使用 ASP.NET Core 2.2)

namespace RestaurantReviewApi.Controllers {
    [Route("api/restaurants")]
    [ApiController]
    public class RestaurantsController : ControllerBase {
        private readonly RestaurantContext _context;

        public RestaurantsController(RestaurantContext context) {
            _context = context;

            // Create a new Restaurant if collection is empty
            if(_context.Restaurants.Count() == 0) {
                Restaurant firstRestaurant = new Restaurant {
                    Reviews = new List<Review> {
                        new Review { }
                    }
                };

                _context.Restaurants.Add(firstRestaurant);
                _context.SaveChanges();
            }
        }

        // GET: api/restaurants
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Restaurant>>> GetRestaurants() {
            return await _context.Restaurants.ToListAsync();
        }
    }
}
namespace RestaurantReviewApi.Models {
    public class Restaurant {
        public long Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public List<Review> Reviews { get; set; }
        public double AverageRating { get; set; }
    }
}
namespace RestaurantReviewApi.Models {
    public class Review {
        public long Id { get; set; }
        public string Author { get; set; }
        public string Text { get; set; }
        public int Stars { get; set; }
    }
}
namespace RestaurantReviewApi.Models {
    public class RestaurantContext : DbContext {
        public RestaurantContext(DbContextOptions<RestaurantContext> options) : base(options) { }
        public DbSet<Restaurant> Restaurants { get; set; }
    }
}

第一个请求 (https://localhost:port/api/restaurants) 给我这个输出:

[
    {
        "id": 1,
        "name": null,
        "address": null,
        "reviews": [
            {
                "id": 1,
                "author": null,
                "text": null,
                "stars": 0
            }
        ],
        "averageRating": 0.0
    }
]

随后的相同请求给出了这个:

[
    {
        "id": 1,
        "name": null,
        "address": null,
        "reviews": null,
        "averageRating": 0.0
    }
]

解决方案:

[HttpGet]
public async Task<ActionResult<IEnumerable<Restaurant>>> GetRestaurants()
{
     return await _context.Restaurants.Include(r => r.Reviews).ToListAsync();
}

这是一个很常见的错误。即使在使用 C# 和 Entity Framework 多年之后,我发现自己有时也会这样做。确保您的 Reviews 属性 是虚拟的。

public class Restaurant {
    public long Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public virtual List<Review> Reviews { get; set; }
    public double AverageRating { get; set; }
}

这是因为当 Entity Framework 执行查询时,您实际上并没有得到 Restaurant 对象:它是一个自动生成的动态代理 class。因此,EF 必须用 List<System.Data.Entity.DynamicProxies.Review_AF34E90301> 替换您的 List<Review> (末尾的长十六进制字符串)。详情请见https://docs.microsoft.com/en-us/ef/ef6/fundamentals/proxies

对于第一个请求,_context.Restaurants的结果是_context.Restaurants.Count() == 0时控制器中构造函数初始化的值,而不是从数据库中查询。

对于后续相同的请求,您从数据库中查询餐厅。如果要查询相关数据,则应使用Include方法指定要包含在查询结果中的相关数据。

[HttpGet]
public async Task<ActionResult<IEnumerable<Restaurant>>> GetRestaurants()
{
     return _context.Restaurants.Include(r=>r.Reviews).ToList();
}

参考:https://docs.microsoft.com/en-us/ef/core/querying/related-data