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
试图构建一个简单的 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